Circular call stack detected for recursive partialCached since 0.146.7

Building sites with recursive partialCached calls stopped since Hugo 0.146.7 with the following error:

Start building sites …
hugo v0.146.7-1ad3d39dc4693434505fc81f91eed57333017e93 windows/amd64 BuildDate=2025-04-22T17:26:42Z VendorInfo=gohugoio

ERROR render of "C:/Daten/Soren/hugo-testing/themes/test/content/_index.md" failed: "C:\Daten\Soren\hugo-testing\themes\test\layouts\_default\all.html:6:61": execute of template failed: template: all.html:6:61: executing "main" at <partialCached "inline/page-walker" . .Path>: error calling partialCached: template: all.html:14:57: executing "partials/inline/page-walker" at <partialCached "inline/page-walker" . .Path>: error calling partialCached: circular call stack detected in partial ""
Built in 41 ms
Error: error building site: render: failed to render pages: render of "/tags" failed: "C:\Daten\Soren\hugo-testing\themes\test\layouts\_default\all.html:6:61": execute of template failed: template: all.html:6:61: executing "main" at <partialCached "inline/page-walker" . .Path>: error calling partialCached: template: all.html:14:57: executing "partials/inline/page-walker" at <partialCached "inline/page-walker" . .Path>: error calling partialCached: circular call stack detected in partial ""

It does not seem to make a difference if the called partial is inline or in a separate file.

Repro:


git clone --single-branch -b hugo-forum-topic-54559 https://github.com/McShelby/hugo-testing hugo-forum-topic-54559
cd hugo-forum-topic-54559
hugo server

Hmm… OK, so I’m guessing you have (partialCached “foo”) ->partial foo->partial foo->partial foo …?

With the introduction of template.Current, we now have the full execution stack, so I replaced the “deadlock timeout” (partialCached “foo” => partialCached “foo” was a deadlock in Hugo 0.145).

If the above is a correct description of the problem I guess we could fix it, but a workaround would also be to do the recursion in a different partial.

The code is solely in hugo-testing/themes/test/layouts/_default/all.html at hugo-forum-topic-54559 · McShelby/hugo-testing · GitHub

{{ define "main" }}
  <h1>{{ .Title }}</h1>
  {{ .Content }}
  <ul>
  {{ range .Pages }}
    <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>{{ partialCached "inline/page-walker" . .Path | safeHTML }}</li>
  {{ end }}
  </ul>
{{ end }}

{{- define "partials/inline/page-walker" }}
<ul>
{{ range .Pages }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>{{ partialCached "inline/page-walker" . .Path | safeHTML }}</li>
{{- end }}
</ul>
{{- end }}

It works if I replace the partialCached calls with calls to partial.

The only way your construct does not deadlock is because the same cache key isn’t repeated when doing the recursion, which is 1) Hard to reason about and 2) If the cache key isn’t repeated, caching doesn’t help (or, you may get some effect in another loop, but 1) still the reason I would avoid this).

I don’t think caching will help in your example. If so, I would split it into 2 partials and do the recursion in the second one and cache the first one.

1 Like

Just to be clear:

  • In Hugo < 0.146.7, any such deadlock would eventually timeout with a panic.
  • In current Hugo, you get an pretty good error message about it at once, no deadlock. Unless someone can come up with a implementation without the (rare) false negatives above, I think this is a good trade off.