.Scratch.SetInMap doesn't work in ranges in certain cases

I have a bizarre issue that has been driving me nuts for several days :rage:, and I’m pretty convinced that either I’m doing something completely stupid, or this is a bug in Hugo or Go itself :man_shrugging:

Here’s an example where I try to set an item in a map from within a loop:

{{ .Scratch.SetInMap "greetings" "english" "Hello" }}
{{ .Scratch.SetInMap "greetings" "French" "Bonjour" }}

{{range $index, $page := .Site.RegularPages}}
  {{ .Scratch.SetInMap "greetings" "russian" "Privet" }}
{{end}}

Greetings: {{.Scratch.Get "greetings"}}

The result I get (notice, no ‘Russian’ in the map):

Greetings: map[english:Hello french:Bonjour]

To try to work around this, I decided maybe I should try using .Site.Pages instead of .Site.RegularPages.

{{ .Scratch.SetInMap "greetings" "english" "Hello" }}
{{ .Scratch.SetInMap "greetings" "french" "Bonjour" }}


{{range $index, $page := .Site.Pages}}
  {{ .Scratch.SetInMap "greetings" "russian" "Privet" }}
{{end}}

Greetings: {{.Scratch.Get "greetings"}}

Sure enough, it works perfectly:

Greetings: map[russian:Privet english:Hello french:Bonjour]

Ok… so now by any normal logic this must mean that that there are 0 regular pages which is the only reason why a loop wouldn’t run. So I added an asterisk every time it loops so I can visualize how many times it’s running:

{{range $index, $page := .Site.RegularPages}}
  <div>*</div>
  {{ .Scratch.SetInMap "greetings" "russian" "Privet" }}
{{end}}

And I get a row of asterisks indicating that the loop is in fact running:

*
*
*
*
*
*
*

Ok so at this point I’m completely baffled. The loop works perfectly fine, yet whenever I use .Site.RegularPages it completely breaks .Scratch.SetInMap, leaving me to think that this has to be a bug.

Thanks in advance, and thanks for the amazing project :+1:

Version Info

Hugo Static Site Generator v0.42.1 darwin/amd64

You are inside the range context, so the .Scratch here is not the same as the .Scratch outside the range. Try printing out {{.Scratch.Get "greetings"}} from inside the range and you will notice it only sees russian, not english or french.


See if this works:

{{range $index, $page := .Site.RegularPages}}
  {{ $.Scratch.SetInMap "greetings" "russian" "Privet" }}
{{end}}

For a better explanation, the docs links to this very helpful post.

Wow, thanks! This pitfall should be added to the docs… it’s almost impossible to figure that out otherwise.