{"record":{"id":"59825a66bbef044d","repo":"gohugoio/hugo","slug":"maximum-template-call-stack-size-exceeded-in-q","errorCode":null,"errorMessage":"maximum template call stack size exceeded in %q","messagePattern":"maximum template call stack size exceeded in %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/tplimpl/templatestore.go","lineNumber":541,"sourceCode":"\ttempl := ti.Template\n\n\tparent := tpl.Context.CurrentTemplate.Get(ctx)\n\tvar level int\n\tif parent != nil {\n\t\tlevel = parent.Level + 1\n\t}\n\tcurrentTi := &tpl.CurrentTemplateInfo{\n\t\tParent:                 parent,\n\t\tLevel:                  level,\n\t\tKey:                    key,\n\t\tCurrentTemplateInfoOps: ti,\n\t}\n\n\tctx = tpl.Context.CurrentTemplate.Set(ctx, currentTi)\n\n\tconst levelThreshold = 999\n\tif level > levelThreshold {\n\t\treturn fmt.Errorf(\"maximum template call stack size exceeded in %q\", ti.Filename())\n\t}\n\n\tif t.opts.Metrics != nil {\n\t\tdefer t.opts.Metrics.MeasureSince(templ.Name(), time.Now())\n\t}\n\n\texecErr := t.storeSite.executer.ExecuteWithContext(ctx, ti, wr, data)\n\tif execErr != nil {\n\t\treturn t.addFileContext(ti, \"execute of template failed\", execErr)\n\t}\n\treturn nil\n}\n\nfunc (t *TemplateStore) GetFunc(name string) (reflect.Value, bool) {\n\tv, found := t.storeSite.execHelper.funcs[name]\n\treturn v, found\n}\n","sourceCodeStart":523,"sourceCodeEnd":559,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/tplimpl/templatestore.go#L523-L559","documentation":"Hugo guards against infinite recursion in template execution by tracking the nesting level of partial/template calls. In ExecuteWithContextAndKey (templatestore.go:539-541) a hard threshold of 999 is enforced: each nested ExecuteWithContext increments the level via the CurrentTemplateInfo parent chain, and when it exceeds 999 the named template's filename is reported. This prevents stack overflows from mutually-recursive partials or templates that include themselves.","triggerScenarios":"A template partial calls itself directly or transitively (e.g. partial A includes partial B which includes partial A), or a layout includes itself via {{ template \"_default/list.html\" . }}. Triggered during site build/render when ExecuteWithContextAndKey recurses past level 999.","commonSituations":"A recursive partial used to render a tree/menu structure (e.g. nav) without a base-case termination check; a baseof/layout that accidentally re-includes itself after a rename or refactor; upgrading Hugo versions where partial context passing changed and a guard condition now never hits nil.","solutions":["Identify the template named in the error and trace its include chain to find the cycle.","Add a base-case guard in the recursive partial (e.g. {{ if .Pages }}...{{ partial \"nav\" . }}{{ end }} or pass a depth counter and stop recursing).","Use Hugo's built-in constructs (range over .Pages) instead of manual recursion through partials.","Temporarily enable template metrics/instrumentation to see which partial is invoked repeatedly."],"exampleFix":"// before — recursive partial layouts/partials/nav.html\n{{ partial \"nav\" . }}\n\n// after — guard against nil/empty to terminate recursion\n{{ with .Pages }}\n  {{ range . }}\n    {{ partial \"nav\" . }}\n  {{ end }}\n{{ end }}","handlingStrategy":"validation","validationCode":"// In a recursive partial, always guard the recursion before calling partial\n{{ with .Pages }}\n  {{ range . }}\n    {{ partial \"nav\" . }}\n  {{ end }}\n{{ end }}\n\n// Or pass a depth counter and stop at a safe limit\n{{ if lt .Depth 50 }}\n  {{ partial \"nav\" (dict \"node\" .Node \"depth\" (add .Depth 1)) }}\n{{ end }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include a base case (empty/nil check) before any recursive partial call.","Prefer Hugo's range over nested data over manual recursion through partials.","Lint templates for partials that reference themselves by name."],"tags":["template","recursion","partial","stack-overflow","build"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}