What can cause infinite recursion? Can dumping taxonomies cause it?

Hi everyone,

I started digging into HUGO recently so sorry if my question seems obvious (:sweat_smile: ) or if it has already been answered (I’ve searched the forum first ofc).
I’ve been trying to modify a theme to add an hyperlink when author is a taxonomy for the website. Being a HUGO newbie I wasn’t sure (even after reading Taxonomies | Hugo and Taxonomies | Hugo) how to deal with them, precisely how to test if author is in .Site.Taxonomies so I added a debug line to that piece of code (in src/themes/poison/layouts/partials/post/info.html) :

{{ if .Params.author }}
  {{ debug.Dump .Site.Taxonomies }}
  {{ if in .Site.Taxonomies "author" }}
    <span><a href="{{ .Site.BaseURL }}author/{{ .Params.author | urlize }}">{{ .Params.author }}</a> - </span>
  {{ else }}
    <span>{{ .Params.author }} - </span>
  {{ end }}
{{ end }}

and instantly the website stopped building, I’ve tested with some flags like hugo serve --trace /tmp/hugo.trace --logLevel debug --printMemoryUsage --templateMetrics --templateMetricsHints for example and here is some behaviors I got:

± hugo serve --trace /tmp/hugo.trace --logLevel debug --printMemoryUsage --templateMetrics --templateMetricsHints
Watching for changes in /home/ctmbl/Documents/iScsc/blog.iscsc.fr/src/{content,themes}
Watching for config changes in /home/ctmbl/Documents/iScsc/blog.iscsc.fr/src/config.toml, /home/ctmbl/Documents/iScsc/blog.iscsc.fr/src/themes/poison/config.toml
Start building sites …
hugo v0.123.7+extended linux/amd64 BuildDate=unknown

INFO  build:  step process substep collect files 17 files_total 17 duration 10.245398ms
INFO  build:  step process duration 10.471928ms
INFO  build:  step assemble duration 4.008944ms
INFO  static: syncing static files to / duration 84.477311ms
INFO  deprecated: .Site.DisqusShortname was deprecated in Hugo v0.120.0 and will be removed in a future release. Use .Site.Config.Services.Disqus.Shortname instead.


Alloc = 1.1 GB
TotalAlloc = 1.8 GB
Sys = 1.7 GB
NumGC = 17



Alloc = 2.1 GB
TotalAlloc = 3.4 GB
Sys = 2.9 GB
NumGC = 18



Alloc = 4.3 GB
TotalAlloc = 6.1 GB
Sys = 5.6 GB
NumGC = 19



Alloc = 6.1 GB
TotalAlloc = 9.5 GB
Sys = 8.8 GB
NumGC = 20

INFO  dynacache: adjusted partitions' max size evicted 18 numGC 20 limit 3.72 GB alloc 5.70 GB totalAlloc 8.83 GB


Alloc = 6.4 GB
TotalAlloc = 10.8 GB
Sys = 9.3 GB
NumGC = 21

ERROR render of "page" failed: "/home/ctmbl/Documents/iScsc/blog.iscsc.fr/src/themes/poison/layouts/_default/single.html:3:5": execute of template failed: template: _default/single.html:3:5: executing "main" at <partial "post/info.html" .>: error calling partial: partial "post/info.html" timed out after 30s. This is most likely due to infinite recursion. If this is just a slow template, you can try to increase the 'timeout' config setting.
INFO  build:  step render pages 44 content 2 duration 30.229430537s
INFO  build:  step postProcess duration 30.929µs

Template Metrics:

     cumulative       average       maximum      cache  percent  cached  total
       duration      duration      duration  potential   cached   count  count  template
     ----------      --------      --------  ---------  -------  ------  -----  --------
  3m30.341162627s  23.371240291s  30.044079151s          0        0       0      9  _default/single.html
  30.103776347s  30.103776347s  30.103776347s          0        0       0      1  index.html
   682.382795ms   15.869367ms   90.410278ms         82        0       0     43  partials/head/head.html
   459.058296ms   10.675774ms   73.400764ms        100        0       0     43  partials/head/scripts.html
    427.90087ms   13.803253ms   77.604498ms          0        0       0     31  _default/list.html
   216.084572ms    5.025222ms    34.47949ms        100        0       0     43  partials/sidebar/sidebar.html
   100.177038ms  100.177038ms  100.177038ms          0        0       0      1  about/about.html
   100.124879ms  100.124879ms  100.124879ms          0        0       0      1  404.html
    80.918842ms    1.881833ms    11.23619ms        100        0       0     43  partials/sidebar/menu.html
    74.352478ms    1.729127ms    9.912696ms        100        0       0     43  partials/head/stylesheets.html
    58.197166ms    1.353422ms    5.303472ms         81        0       0     43  partials/head/meta.html
    42.262024ms   21.131012ms   40.663268ms         69        0       0      2  partials/post/info.html
    38.023794ms     884.274µs    3.824513ms        100        0       0     43  partials/head/css.html
    30.401095ms     707.002µs    5.037608ms        100        0       0     43  partials/sidebar/socials.html
    16.667808ms    1.282139ms    5.759158ms          0        0       0     13  _internal/shortcodes/highlight.html
     8.954798ms    4.477399ms    8.874906ms          0        0       0      2  shortcodes/plantuml.html
     8.250268ms     191.866µs    2.728532ms        100        0       0     43  partials/sidebar/title.html
      6.74504ms     156.861µs    1.077166ms        100        0       0     43  partials/sidebar/copyright.html
     6.390186ms    6.390186ms    6.390186ms          0        0       0      1  _internal/_default/sitemap.xml
     1.761546ms     110.096µs     708.024µs          0        0       0     16  _default/_markup/render-link.html
     1.072176ms     536.088µs     715.789µs         54        0       0      2  partials/post/navigation.html
       542.53µs     271.265µs     423.695µs          0        0       0      2  shortcodes/tab.html
       532.03µs      532.03µs      532.03µs          0        0       0      1  shortcodes/mermaid.html
      524.566µs     524.566µs     524.566µs          0        0       0      1  shortcodes/tabs.html
      449.444µs     224.722µs     390.422µs         58        0       0      2  partials/table_of_contents.html
      376.305µs     188.152µs     305.931µs          0        0       0      2  _internal/alias.html
      367.206µs       8.539µs     195.611µs        100        0       0     43  partials/light_dark.html

INFO  build:  duration 30.25828214s


Alloc = 6.6 GB
TotalAlloc = 13.6 GB
Sys = 9.9 GB
NumGC = 21

Built in 51544 ms


Alloc = 7.6 GB
TotalAlloc = 14.6 GB
Sys = 10.7 GB
NumGC = 21



Alloc = 7.6 GB
TotalAlloc = 14.6 GB
Sys = 10.7 GB
NumGC = 22



Alloc = 7.6 GB
TotalAlloc = 14.6 GB
Sys = 10.7 GB
NumGC = 22

Error: error building site: render: failed to render pages: render of "home" failed: "/home/ctmbl/Documents/iScsc/blog.iscsc.fr/src/themes/poison/layouts/index.html:6:11": execute of template failed: template: index.html:6:11: executing "main" at <partial "post/info.html" .>: error calling partial: partial "post/info.html" timed out after 30s. This is most likely due to infinite recursion. If this is just a slow template, you can try to increase the 'timeout' config setting.

This is the most explicit one but before getting it (by adding the flags I gave earlier) I encountered:

± hugo serve --trace /tmp/hugo.trace --logLevel debug --printMemoryUsage
Watching for changes in /home/ctmbl/Documents/iScsc/blog.iscsc.fr/src/{content,themes}
Watching for config changes in /home/ctmbl/Documents/iScsc/blog.iscsc.fr/src/config.toml, /home/ctmbl/Documents/iScsc/blog.iscsc.fr/src/themes/poison/config.toml
Start building sites …
hugo v0.123.7+extended linux/amd64 BuildDate=unknown

INFO  build:  step process substep collect files 17 files_total 17 duration 4.306872ms
INFO  build:  step process duration 4.49526ms
INFO  build:  step assemble duration 4.672218ms
INFO  static: syncing static files to / duration 74.620268ms
INFO  deprecated: .Site.DisqusShortname was deprecated in Hugo v0.120.0 and will be removed in a future release. Use .Site.Config.Services.Disqus.Shortname instead.
fatal error: concurrent map iteration and map write

goroutine 206 [running]:
reflect.mapiternext(0x55bd82aacbc0?)
	runtime/map.go:1392 +0x13
...
(the backtrace goes on on more than a thousand lines)

I even got a kill of hugo process for out-of-memory
from journalctl:

mars 24 17:57:06 ctmbl-laptop-manjaro kernel: [   3184]  1000  3184  3764914  2847163 23166976        0           200 hugo
mars 24 17:57:06 ctmbl-laptop-manjaro kernel: oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1000.slice/u>
mars 24 17:57:06 ctmbl-laptop-manjaro kernel: Out of memory: Killed process 3184 (hugo) total-vm:15059656kB, anon-rss:11388524kB, file-rss:128kB, shmem-rss:0kB, UID:1000 pgt>
mars 24 17:57:04 ctmbl-laptop-manjaro kwin_wayland[677]: kwin_libinput: Libinput: client bug: timer event7 hold: scheduled expiry is in the past (-142ms), your system is too>
mars 24 17:57:06 ctmbl-laptop-manjaro systemd-journald[285]: Under memory pressure, flushing caches.

I’m pretty sure that the issue, and solution, is really simple but I can’t see it with my limited knowledge, if someone has an idea :sweat_smile:

Environment:
Linux 6.6.19-1-MANJARO #1 SMP PREEMPT_DYNAMIC Fri Mar 1 18:16:16 UTC 2024 GNU/Linux
hugo v0.123.7+extended linux/amd64 BuildDate=unknown

Thanks in advance for your help :blush:

Ok I feel stupid I found that to get the behavior I wanted I just had to do:

{{ if .Params.author }}
  {{ if .Site.Taxonomies.author }}
    <span><a href="{{ .Site.BaseURL }}author/{{ .Params.author | urlize }}">{{ .Params.author }}</a> - </span>
  {{ else }}
    <span>{{ .Params.author }} - </span>
  {{ end }}
{{ end }}

But I’m still interested in knowing what could have caused the issue I encountered earlier :slight_smile:

See https://github.com/gohugoio/hugo/issues/12309.

Your example is a bit fragile, and there is a never a good reason to use .Site.BaseURL in a template. At some point we will deprecate that method.

This is a cleaner approach:

{{ with .Params.author }}
  {{ with site.Taxonomies.author.Get . }}
    <span><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> - </span>
  {{ else }}
    <span>{{ . }} - </span>
  {{ end }}
{{ end }}

With v0.123.3 and later you should add this to your site configuration:

capitalizeListTitles = false
2 Likes

Thanks a lot I’ll take a look at the issue and the fix :wink:!

I realized the issues of using .Site.BaseURL and finally came up with this code:

{{ if .Params.author }}
  {{ $author := .Params.author }}
  {{ $authorURLized := ($author | urlize) }}
  {{ with .Site.GetPage "author" }}
    <span><a href="{{ (.GetPage $authorURLized).Permalink }}">{{ $author }}</a> - </span>
  {{ else }}
    <span>{{ .Params.author }} - </span>
  {{ end }}
{{ end }}

But yours is exactly what I wanted to do, so thanks!
Just a quick question: why use RelPermalink and not Permalink?

Preference. Why provide scheme+host when that’s already inferred? There are a few places where you should use Permalink such as:

  • canonical link elements
  • rss feeds
  • sitemaps
  • structured data
  • opengraph meta elements
1 Like

Ok I get it, thanks a lot for taking the time to answer!
I’ll keep that in mind in future template development :wink:

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.