Error index of nil pointer accessing values in a map using a slice with dynamic keys

Hello,

I want to acces the value from a map using a slice of keys computed from the page path but using the index function on a map with a dynamically created slice, gives the error:
<index $map $paths>: error calling index: index of nil pointer

I will provide here an example that emulates my real scenario:

  • I extract the strings from the page path using the split function which returns a slice with the strings.
  • I create a map with nested maps with the same keys from the path strings.
  • I use the index function with the map and the slice as arguments in order to access the value from the map based on the keys from the slice and it gives the error from above.
<p>Path: {{.Page.RelPermalink}}</p>   => Path: /products/electronics/laptops

{{ $path :=  trim .Page.RelPermalink "/" }}
<p>Page path: {{$path}}</p>  => Page path: products/electronics/laptops

{{$paths := split $path "/"}}
<p>Paths: {{$paths}} len: {{len $paths}}</p>  => Paths: [products electronics laptops] len: 3
{{ reflect.IsSlice $paths }} → true

{{ $map2 := dict "laptops" "asus" }}
{{ $map1 := dict "electronics" $map2 }}
{{ $map := dict "products" $map1 }}

<p>Value: {{index $map $paths}}</p>  => Error: failed to render shortcode at <index $map $paths>: error calling index: index of nil pointer

I also tried this approaches and it still doesn’t work:

<p>Value: {{index (index $map (index $paths 0)) (index $paths 1) }} </p> =>  Error: index of nil pointer
<!-- or -->
{{$temp := index $map (index $paths 0)}} => Works only for the first key
<p>Value: {{index $temp (index $paths 1) }} </p> =>  Error: index of nil pointer
<!-- or -->
{{$paths1 := index $paths 1}}
<p>Value: {{index $temp $paths1) }} </p> =>  Error: index of nil pointer

However if I manually create the slice with the keys and use it as an argument for the index function it works:

{{$slicePath := slice "products" "electronics" "laptops"}}
<p>Value: {{index $map $slicePath }}</p> => Value: asus

My question is: Why the dynamically computed slice used as an argument for the index function give the nil pointer error even if it is not nil? Is this a known issue in Hugo? Is there a way to do more debugging on this?

One or more of the pages rendered by this template does not have a corresponding entry in the map.

When using the index function with more than one key, if the second or greater key does not exist, the function throws an error.

Examples:

{{ $m := dict "a" 1 }}

{{ index $m "a" }} --> 1
{{ index $m "a" "b" }} --> error: can't index item of type int

{{ index $m "b" }} --> nil
{{ index $m "b" "c" }} --> error: index of nil pointer

You can code defensively with something like:

{{ $m := dict
  "products" (dict
    "electronics" (dict
      "laptops" "asus"
    )
  )
}}
{{ $p := split (trim .Page.RelPermalink "/") "/" }}

{{ $key := slice }}
{{ $result := "" }}
{{ range $p }}
  {{ $result = "" }}
  {{ $key = $key | append . }}
  {{ with index $m $key }}
    {{ $result = . }}
  {{ else }}
    {{ break }}
  {{ end }}
{{ end }}

{{ with $result }}
  <p>Value: {{ . }}</p>
{{ end }}

Hi @jmooring

I understand that the error: index of nil pointer is thrown when one of the nested keys doesn’t exist in the map but the question is:
How can one of the keys from the slice, not be in the map when executing the index function since the path strings are the same with the ones from the slice when they are displayed in html paragraphs?

{{ $path :=  trim .Page.RelPermalink "/" }}
{{$paths := split $path "/"}}
<p>Paths displayed: {{$paths}} len: {{len $paths}}</p> → Paths displayed: [products electronics laptops] len: 3
{{ reflect.IsSlice $paths }} → true

{{ $map2 := dict "laptops" "asus" }}
{{ $map1 := dict "electronics" $map2 }}
{{ $map := dict "products" $map1 }}

I tried the approach from your code implementation and it gives the same error!

Can you share your repository? Without looking at everything I would just be guessing.

But again, consider this:

1 Like