Code sometimes does not output anything

Hello,

hugo v0.152.2+extended linux/amd64 BuildDate=2025-12-14T00:00:00+00:00 VendorInfo=Fedora:0.152.2-1.fc43

I use this shortcode to show a site map and it works fine (The reason I am showing this code is because my code below is based on it but does not work)

{{ define “listpages” }}

{{ if .Pages }}
	<ul>
		 {{ range .Pages}}
			 <li><a href="{{ .Permalink }}">{{ .Title }}</a>
				  {{ template "listpages" . }}
			 </li>
		 {{ end }}
	</ul>
{{ end }}

{{ end }}

<ul>
{{ range .Site.Sections }}
    <li><a href="{{ .Permalink }}">{{ .Title }}</a>
        {{ template "listpages" . }}</li>
{{ end }}
</ul>

I am trying to create a shortcode where I can specify the starting (top-level) section and well as the depth of subsections / subpages to output. IE a shortcode that displays subsections and subpages of a given section.

This code works fine BUT the problem I am having is that sometimes it does not output anything at all - it seems to be an intermittent problem. I have spent many hours trying to debut this. Asking AI in this case starts a viscous cycle of it 1) recommeding fixed code 2) that code not working or producing errors and going back to step 1 over and over.


{{ $section := .Get "section" }}
{{ $maxdepth := .Get "maxdepth" | default 0 | int }}
{{ $start := site.GetPage "section" $section }}

{{ define "listpages-recurse" }}
  {{ $page := .page }}
  {{ $level := .level }}
  {{ $max := .max }}

  {{ if or (eq $max 0) (le $level $max) }}
    {{ if $page.Pages }}
      <ul>
        {{ range $page.Pages }}
          <li>
            <a href="{{ .Permalink }}">{{ .Title }}</a>
            {{ template "listpages-recurse" (dict
              "page" .
              "level" (add $level 1)
              "max" $max
            ) }}
          </li>
        {{ end }}
      </ul>
    {{ end }}
  {{ end }}
{{ end }}

{{ if $start }}
  {{ template "listpages-recurse" (dict
    "page" $start
    "level" 1
    "max" $maxdepth
  ) }}
{{ else }}
  <p>Section "{{ $section }}" not found.</p>
{{ end }}




I call this shortcode using eg:


{{< list-subsections-and-subpages section="steps" maxdepth="2" >}}

Any help much appreciated.

update based on input from (thc jmooring)

site.GetPage expects a path not two values.

Your code uses the old style which should still be supported.

To be on the safe side change it to

{{ $start := site.GetPage $section }}

Both for a simple setup work fine.

Some more hints when it fails or even bettera reproducible setup ?

1 Like

@ irkode Thank you very much for your reply and assistance.

I changed it to

{{ $start := site.GetPage $section }}

and that does work, but the unfortunately the problem persists.

Hugo never reports an error message.

If I stop and re-start Hugo as well as my browser and I have my browser open the page in question automatically at start, then the shortcode does not output anything. BTW I start Hugo using:

hugo server -D --disableFastRender --ignoreCache

Hugo on startup just reports:
Built in 815 ms
Environment: “development”
Serving pages from disk
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)

BUT I also just noticed that when I make changes to the shortcode file, then the shortcode does output and I can see the output in the page I call the shortcode in.

Hugo reports:
Change detected, rebuilding site (#1).
2026-02-23 13:25:13.756 -0500
Template changed /_shortcodes/list-subsections-and-subpages.html
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Total in 241 ms

So it seems the shortcode does output when the site is rebuilt.

So maybe the site is not being rebuilt correctly some of the time?

might be …

I cleaned public, started hugo server and a fresh browser - works as expected.

As stated before: Are you able to prepare a reproducible repo with the steps to replay your problem - does not make much sense to try to figure out what you have.

1 Like

Hi @irkode - Unfortunately I am not at a level to be able to use github and provide a repo if that is what you mean.

I realize that you cannot help me without seeing the whole site code though, but I thank you for the help you have given me so far.

Not being able to provide a github repo, what I have done in the past is just created a new site with new theme and I will test that way and report back.

mmh. a zip of your project folder nd afile share service?

1 Like

Thank you for suggesting that. If you dont mind I will first test using a clean site and just the shortcode in question - I find I learn a lot doing that :slight_smile:

There are some things to try

hugo [server] --logLevel debug --printPathWarnings

will add more output and hints on publishing pages to the same path.

are you using the shortcode on

  • many pages?
  • multiple times on the same page

I never used define/template inside a shortcode. I usually create a standard _partial/listpages-recurse that I call the shortcode. as `partial “listpages-recurse” (dict “page” $start “level” …) maybe worth a try to externalize that one

might be a caching or redefinition problem… hard to tell

1 Like

Thank you for your continued help :slight_smile:

I am using the shortcode on one page and one time on that page.

Thanks for suggesting an alternative way to code. I am currently not able to understand how to do that so I will have to go thru a learning curve.

But I decided to revert the code of the shortcode to an earlier version where I had just added the ability to pass the section parameter. And before I had added the abiltity to pass the depth,

And this code works all the time:

{{ $section := .Get "section" }}
{{ $start := site.GetPage "section" $section }}

{{ define "listpages-recurse" }}
  {{ if .Pages }}
    <ul>
      {{ range .Pages }}
        <li>
          <a href="{{ .Permalink }}">{{ .Title }}</a>
          {{ template "listpages-recurse" . }}
        </li>
      {{ end }}
    </ul>
  {{ end }}
{{ end }}

{{ if $start }}
  {{ template "listpages-recurse" $start }}
{{ else }}
  <p>Section "{{ $section }}" not found.</p>
{{ end }}

So correct me if I am wrong but I would think this means there is not an issue with other parts of the site. The issue must be within the code I added to handle the maxdepth.

Or the issue is there but pops out when you add more parameters

an inline partial example in the docs uses : {{- define "_partials/inline/menu/walk.html" }} and calls it like that {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }}

also worth a try

1 Like

@irkode Thank you for your further suggestions. I will learn how to do an inline partial and test that out.

I hope you are not frustrated that I am not providing what you requested. I cannot provide a github repo - that is something I dont have the skill to do as yet. As for uploading a zip file, I would have to get permission first.

no worries all fine for me

it does not have to be an inline partial, a regular one will do.

_shortcodes/listpages.html

{{ $section := .Get "section" }}
{{ $maxdepth := .Get "maxdepth" | default 0 | int }}
{{ $start := site.GetPage "section" $section }}

{{ if $start }}
  {{ partial "listpages-recurse" (dict
    "page" $start
    "level" 1
    "max" $maxdepth
  ) }}
{{ else }}
  <p>Section "{{ $section }}" not found.</p>
{{ end }}
_partials/listpages-recurse.html
{{ $page := .page }}
{{ $level := .level }}
{{ $max := .max }}

{{ if or (eq $max 0) (le $level $max) }}
  {{ if $page.Pages }}
    <ul>
      {{ range $page.Pages }}
        <li>
          <a href="{{ .Permalink }}">{{ .Title }}</a>
          {{ partial "listpages-recurse" (dict
            "page" .
            "level" (add $level 1)
            "max" $max
          ) }}
        </li>
      {{ end }}
    </ul>
  {{ end }}
{{ end }}

but as I said no differences for me … btw I’m on version 0.156.0

1 Like

@irkode Thanks very much for providing the sample code! :slight_smile:

just one thing came back to my head:

do you have a backup of your shortcode in your layouts folder, that also defines the inline partial?

if so move it out from layouts folder. and try again.

2 Likes

Wow, that seems to have done the trick!

I backup eg shortcode files by copying a file, adding the date and some comments in the filename and ending the filenames with .backup.

In hugo.toml I have:

ignoreFiles = [“\.backup$”]

and so I thought making backup of files like this would be ok.

I have many .backup copies of many different partial and shortcode files in the theme’s layouts and _shortcodes folders and I deleted all .backup files and now the problem seems (pending some more testing) to have gone away!

Eg now when I do a restart of Hugo and my browser, the shortcode’s output IS displayed!

I noticed too that Hugo is taking about a half second more to generate the site, presumably partially due to generating the output of this shortcode.

Thank you very very much for suggesting this :slight_smile:

I also noticed that if I have shorcode.html and shortcode.html.backup, and I delete shortcode.html then Hugo will use shortcode.html.backup when the shortcode is called.

If possible could you explain why this fixed the issue? I would like to learn so I can avoid similar things in future…..

That’s why people use GitHub (or versioning systems in general): You do not have to jump through a stack of loops just to have a versioning history of your files.

according to the docs ignoreFiles that does not apply to layouts

against the absolute file path and apply to files within the content , data , and i18n directories

Issue 1:

I remember I also noticed that once …

might be a bug/glitch in the shortcode lookup order

Issue 2:

I remembered having that issue when adapting the menu example from the docs and mad a backup with another name like a-menu.html. just forgot about…

all files below layouts are read as templates and cached for being applied in case a lookup matches. This is done regardless of a layout is actually triggered.

Inline partials are also in the globally defined.

  • if you define an inline partial with the same name in ONE file, Hugo errors out with an error.
  • if you have two files (shortcode/partial) defining an inline partial with the same name, it does not. I’m not sure what happens exactly, but the actual inline partial used seems to depend on parsing and/or execution order of the parant template.

So I’ts not really a problem having some backup files in that layouts, but the double definition of an inline partial with the same name in two files.

Maybe that should error/warn when parsing the layouts.

Issue 2 logged as: Duplicate definition of an inline partial in two different files is not handled properly · Issue #14561 · gohugoio/hugo · GitHub

1 Like

@irkode Thanks for further explaining things - that really helps me to understand how Hugo is operating. For example I had assumed only called files below layouts would be read as templates and cached but now I understand that is not the case.

Update - It turns out that removing any backup files from the _shortcodes folder did NOT fix the issue.

I have now switched to using the code that was suggested irkode (thanks again for this code):slight_smile:

mmh … just to clarify it’s not only shortcodes. it’s any definition of that inline template also in any other file under layouts recursively.

maybe there’s another one

p.s. if you are ready to share a non working state I may have a look

2 Likes