Another interesting case with Hugo If and Range not working as they should

Here is some code I have which should prevent going over the range when there is no value(in testing the len is definitely 0 and the $d = map[]

{{ $data := newScratch }}
{{$d := where (where (where .Params.featured_post.post_options "visible" true) "date" "le" time.Now ) "expiry_datetime" "ge" time.Now   }}

{{if gt (len $d) 0 }}
  {{range $p :=  where (where (where .Params.featured_post.post_options "visible" true) "date" "le" time.Now ) "expiry_datetime" "ge" time.Now}}
    {{ $data.Set "ftimage" $p.image }}
    {{ $data.Set "featured_title" $p.title }}
    {{ $data.Set "ftdate" $p.date }}
    {{ $data.Set "ftperma" $p.url }}
    {{ $data.Set "summary_text" $p.summary_text }}
  {{end}}
{{end}}

However I get this error

executing "partials/main/featured.html" at <where .Params.featured_post.post_options "visible" true>: error calling where: can't iterate over <nil>

My understanding is that it shouldn’t even call the range due to being wrapped in an IF. However I’m all open to suggestions into how to detect a nil value before ranging.

Are you sure your ‘inner’ wheres are non-nil? This doesn’t look like range issue this looks like an outer where is getting a nil from an inner where.

Thanks for the response. However, given the if statement above it should even enter the range statement correct?

you could even write

{{if eq 1 0 }}
  {{range $p :=  where (where (where .Params.featured_post.post_options "visible" true) "date" "le" time.Now ) "expiry_datetime" "ge" time.Now}}
    {{ $data.Set "ftimage" $p.image }}
    {{ $data.Set "featured_title" $p.title }}
    {{ $data.Set "ftdate" $p.date }}
    {{ $data.Set "ftperma" $p.url }}
    {{ $data.Set "summary_text" $p.summary_text }}
  {{end}}
{{end}}

And it still pulls the same error when it shouldn’t enter the range at all. Unless I have a fundamental misunderstanding of how Hugo runs if statements.

This is failing before the range statement.

Is .Params.featured_post set on every page?
If so, is .Params.featured_post.post_options set on every page?

If not, you will have a fail.
If it’s in a layout used by taxonomies or terms it might not even be enough for all content pages to have the above frontmatter.

My question remains why is it not cutting out at the if statement. I have reconfigured to :

{{ $data := newScratch }}
{{if eq 1 0 }}
  {{range $p :=  where (where (where .Params.featured_post.post_options "visible" true) "date" "le" time.Now ) "expiry_datetime" "ge" time.Now}}
    {{ $data.Set "ftimage" $p.image }}
    {{ $data.Set "featured_title" $p.title }}
    {{ $data.Set "ftdate" $p.date }}
    {{ $data.Set "ftperma" $p.url }}
    {{ $data.Set "summary_text" $p.summary_text }}
  {{end}}
{{end}}

The main bit I’m seeing a failure is why isn’t

{{if eq 1 0 }}

preventing it from even checking the range/where

I cannot reproduce your error. Please provide a link to the full source repo and commands you use, and version of Hugo and Go.

Also see: Requesting Help

EDIT: Here’s the test case

With the following shortcode:

{{with .Page }}
    {{ if eq 1 0 }}
        {{ range $p := where ( where .Params.does_not_exist "visible" true) "another" false }}
            {{ print $p }}
        {{ end }}
    {{ end }}
{{ end }}

and in a content page:

---
title: "Demo Post"
date: 2021-11-23T00:11:54-05:00
---

Just to make sure the site works

{{< false-if-but-where >}}

Which would exhibit the problem if the if weren’t working. It works for me, therefore there is something more than you are telling us.

Removing the {{ if eq 1 0 }} results in:

execute of template failed: template: shortcodes/false-if-but-where.html:2:31: executing "shortcodes/false-if-but-where.html" at <where .Params.does_not_exist "visible" true>: error calling where: can't iterate over <nil>