{"id":"b38ec3a5382ca394","repo":"gohugoio/hugo","slug":"max-depth-exceeded","errorCode":null,"errorMessage":"max depth exceeded","messagePattern":"max depth exceeded","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"config/defaultConfigProvider.go","lineNumber":252,"sourceCode":"}\n\nfunc (c *defaultConfigProvider) Keys() []string {\n\tc.mu.RLock()\n\tdefer c.mu.RUnlock()\n\tvar keys []string\n\tfor k := range c.root {\n\t\tkeys = append(keys, k)\n\t}\n\tsort.Strings(keys)\n\treturn keys\n}\n\nfunc (c *defaultConfigProvider) WalkParams(walkFn func(params ...hmaps.KeyParams) bool) {\n\tmaxDepth := 1000\n\tvar walk func(depth int, params ...hmaps.KeyParams)\n\twalk = func(depth int, params ...hmaps.KeyParams) {\n\t\tif depth > maxDepth {\n\t\t\tpanic(errors.New(\"max depth exceeded\"))\n\t\t}\n\t\tif walkFn(params...) {\n\t\t\treturn\n\t\t}\n\t\tp1 := params[len(params)-1]\n\t\ti := len(params)\n\t\tfor k, v := range p1.Params {\n\t\t\tif p2, ok := v.(hmaps.Params); ok {\n\t\t\t\tparamsplus1 := make([]hmaps.KeyParams, i+1)\n\t\t\t\tcopy(paramsplus1, params)\n\t\t\t\tparamsplus1[i] = hmaps.KeyParams{Key: k, Params: p2}\n\t\t\t\twalk(depth+1, paramsplus1...)\n\t\t\t}\n\t\t}\n\t}\n\twalk(0, hmaps.KeyParams{Key: \"\", Params: c.root})\n}\n","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/config/defaultConfigProvider.go#L234-L270","documentation":"A panic raised by defaultConfigProvider.WalkParams when recursively walking the site's params/config tree exceeds 1000 nested levels. It is a guard against unbounded recursion — a legitimate Hugo config never approaches this depth, so hitting it almost always means the params tree contains a cycle or pathologically deep nesting.","triggerScenarios":"WalkParams recursing more than 1000 map levels deep — a params map that (directly or via module/theme config merging or programmatic mutation) contains a reference cycle, or genuinely 1000+ levels of nested maps in config/params.","commonSituations":"Generated or machine-produced config/data injected into site params with self-referencing structures; extreme auto-generated nesting in params files; a Hugo bug where config merging creates a cycle — worth reporting upstream since hand-written configs cannot realistically trigger this.","solutions":["Inspect site params for cyclic or absurdly deep nesting — especially any generated/imported config; flatten or break the cycle.","Bisect by removing config mounts/themes/modules until the panic disappears to locate the offending source.","If the params are reasonable and the panic persists, report it as a Hugo bug with a minimal reproducer, since 1000 levels indicates an internal cycle."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Guard against absurdly deep nesting before handing maps to the config provider\nfunc depth(m map[string]any, d int) int {\n    max := d\n    for _, v := range m {\n        if mm, ok := v.(maps.Params); ok {\n            if dd := depth(mm, d+1); dd > max { max = dd }\n        }\n    }\n    return max\n}\nif depth(params, 0) > 32 { return errors.New(\"config nesting too deep — flatten your params\") }","typeGuard":null,"tryCatchPattern":"if err := provider.SetDefaults(params); err != nil {\n    if strings.Contains(err.Error(), \"max depth exceeded\") {\n        // config maps nested beyond the provider's recursion limit — usually a self-referencing or generated structure\n    }\n    return err\n}","preventionTips":["Keep params nesting shallow (a handful of levels); deep trees usually mean generated or accidentally self-referential config","If you generate config programmatically, assert its depth in your generator's tests","Don't merge a config map into itself (aliasing creates effectively infinite depth)"],"tags":["hugo","config","panic","recursion","params"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}