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 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.
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.
We have the same problem in Istio’s documentation site. I didn’t write this template myself, but am trying to understand how the circular call stack error applies.
<ul>
for each page
if "has children"
<li><a> page name </a>
recurse
</li>
else
<li><a> page name </a></li>
</ul>
There is some logic in the “has children” section to determine if the section being rendered is an ancestor of the current page, in which case the expando will be open, or if it does not, in which case the expando will be closed:
From what I can gather, it seemed reasonable to have the third instance cached, because for a given page, the children are not going to change during the generation of the nav.