.CurrentSection.Params generates nil pointer, even in with

Hi folks.

I’m trying to build a flexible sidebar, where a section can select what sidebar to use. The most common is a full depth tree of all pages in that section. The section can select which sidebar to use by specifying sidebar_type in its front-matter. It doesn’t have to specify anything, however.

That’s the background. The issue I’m running into is in the template, however. Specifically, this:

{{ with .CurrentSection.Params.sidebar_type }}
 Foo
{{end}}

Is generating the dreaded:

Building sites … ERROR 2018/08/07 14:47:14 Failed to render "/home/crell/Platformsh/hugotest/layouts/_default/list.html": runtime error: invalid memory address or nil pointer dereference

Using just {{ with .CurrentSection }} runs. But as soon as I add .Params it starts erroring out. (The error message is entirely unhelpful, of course. It took me over an hour of trial and error to even find what line it was actually complaining about.)

Per this previous thread: Runtime error: invalid memory address or nil pointer dereference

Isn’t the whole point of with that it checks to make sure the values are non-nil and so it’s safe to use? Am I completely misunderstanding what with does (entirely possible), and if so, what should I be doing here instead?

Does anyone know of an existing sample of what I’m trying to do, or a portion thereof, that I can shamelessly copy rather than reinventing it?

Try:

{{ with .CurrentSection }}
{{ .Params.sidebar_type }}
{{end}}

Yes, but you need to do that before you actually use the nil value. As above.

Ah ha! OK, this is what I ended up with, and it doesn’t break on me:

{{ with .CurrentSection }}
    {{ $sidebar_type := .Params.sidebar_type }}

    {{ if eq $sidebar_type  "tree" }}
        {{ partial "sidebar-tree.html" . }}
    {{ else }}
        Some other sidebar here.
    {{ end }}
{{ end }}

So with also shifts the scope. That’s… annoying. Oh well. If I use with to set an arbitrary value, does that also shift the scope to that variable?

You could use {{ if .CurrentSection }} and get the same, I think, without the scope change. But I think it brings clarity to the code (it is shorter), and don’t find it annoying.

In many cases I agree. However, with more complex logic I may want to access something from the original scope. I’ll try the if when that comes up next. Although… wouldn’t it be if .CurrentSection.Param? (Since .CurrentSection always exists but it’s .Param that sometimes doesn’t, if the current page has no custom properties.)

That statement is not true, see hugolib package - github.com/gohugoio/hugo/hugolib - Go Packages

.Params will always be non-nil.

Note that you can acess the original/outer-most scope by $ e.g. $.CurrentSection etc.