{"record":{"id":"7c0b1a1b5e853188","repo":"gohugoio/hugo","slug":"shifter-is-required","errorCode":null,"errorMessage":"Shifter is required","messagePattern":"Shifter is required","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"hugolib/doctree/nodeshifttree.go","lineNumber":88,"sourceCode":")\n\n// NodeShiftTree is the root of a tree that can be shaped using the Shape method.\n// Note that multiplied shapes of the same tree is meant to be used concurrently,\n// so use the applicable locking when needed.\ntype NodeShiftTree[T any] struct {\n\ttree *radix.Tree[T]\n\n\t// [language, version, role].\n\tsiteVector     sitesmatrix.Vector\n\tshifter        Shifter[T]\n\ttransformerRaw Transformer[T]\n\n\tmu *sync.RWMutex\n}\n\nfunc New[T any](cfg Config[T]) *NodeShiftTree[T] {\n\tif cfg.Shifter == nil {\n\t\tpanic(\"Shifter is required\")\n\t}\n\n\treturn &NodeShiftTree[T]{\n\t\tmu: &sync.RWMutex{},\n\n\t\tshifter:        cfg.Shifter,\n\t\ttransformerRaw: cfg.TransformerRaw,\n\t\ttree:           radix.New[T](),\n\t}\n}\n\n// SiteVector returns the site vector of the current dimension.\nfunc (r *NodeShiftTree[T]) SiteVector() sitesmatrix.Vector {\n\treturn r.siteVector\n}\n\n// Delete deletes the node at the given key in the current dimension.\nfunc (r *NodeShiftTree[T]) Delete(key string) (T, bool) {","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/hugolib/doctree/nodeshifttree.go#L70-L106","documentation":"A panic in doctree.New (hugolib/doctree/nodeshifttree.go:88) when Config.Shifter is nil. The NodeShiftTree relies on the Shifter for all dimension operations (Insert/Delete/Shift), so a nil Shifter is rejected at construction time.","triggerScenarios":"Calling doctree.New[T](doctree.Config[T]{}) without setting Shifter.","commonSituations":"Embedded/programmatic use of Hugo's doctree package without supplying a Shifter implementation.","solutions":["Pass a non-nil Shifter in doctree.Config","Reuse Hugo's contentNodeShifter rather than building one from scratch"],"exampleFix":"// before\ntree := doctree.New[contentNode](doctree.Config[contentNode]{})\n// after\ntree := doctree.New[contentNode](doctree.Config[contentNode]{\n    Shifter: &contentNodeShifter{},\n})","handlingStrategy":"validation","validationCode":"if cfg.Shifter == nil {\n    return nil, errors.New(\"doctree.Config.Shifter must be non-nil\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always supply a Shifter when constructing a NodeShiftTree","Reuse Hugo's existing shifter implementations","Unit-test tree construction with a concrete Shifter"],"tags":["doctree","api-misuse","panic"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}