{"record":{"id":"4cec3822c85b360d","repo":"siyuan-note/siyuan","slug":"createdoctree-exceeds-the-maximum-depth-of-d","errorCode":null,"errorMessage":"createDocTree exceeds the maximum depth of %d","messagePattern":"createDocTree exceeds the maximum depth of (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_doc_tree.go","lineNumber":123,"sourceCode":"func parseTemplateDocTreeDefinition(def any) ([]*TemplateDocTreeNode, error) {\n\tstate := &templateDocTreeParseState{}\n\tnodes, err := state.parseNodes(def, 1)\n\tif nil != err {\n\t\treturn nil, err\n\t}\n\tif 0 == len(nodes) {\n\t\treturn nil, errors.New(\"createDocTree requires at least one document\")\n\t}\n\treturn nodes, nil\n}\n\ntype templateDocTreeParseState struct {\n\tcount int\n}\n\nfunc (state *templateDocTreeParseState) parseNodes(value any, depth int) ([]*TemplateDocTreeNode, error) {\n\tif maxTemplateDocTreeDepth < depth {\n\t\treturn nil, fmt.Errorf(\"createDocTree exceeds the maximum depth of %d\", maxTemplateDocTreeDepth)\n\t}\n\tvalues, ok := value.([]any)\n\tif !ok {\n\t\treturn nil, errors.New(\"createDocTree definition must be a list\")\n\t}\n\tif 0 == len(values) {\n\t\treturn nil, errors.New(\"createDocTree document list must not be empty\")\n\t}\n\n\tnodes := make([]*TemplateDocTreeNode, 0, len(values))\n\tfor _, value := range values {\n\t\tdefinition, ok := value.(map[string]any)\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"createDocTree document must be a dictionary\")\n\t\t}\n\t\tfor key := range definition {\n\t\t\tswitch key {\n\t\t\tcase \"title\", \"template\", \"define\", \"children\":","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template_doc_tree.go#L105-L141","documentation":"createDocTree's recursive definition parser (parseNodes) rejects a definition whose nesting exceeds maxTemplateDocTreeDepth (16 levels). The depth counter starts at 1 for the top-level list and increments for each nested \"children\" list. The limit protects the kernel from stack exhaustion and runaway recursive templates when a document-tree template is rendered.","triggerScenarios":"Calling parseTemplateDocTreeDefinition (via the createDocTree template action) with a definition containing more than 16 levels of nested children arrays, e.g. a self-nesting or accidentally duplicated children structure that nests 17+ deep.","commonSituations":"A template author writes deeply nested children lists by hand; a generator or script produces recursive nesting from cyclic data; an LLM generates an over-nested doc-tree template; a previous version allowed more depth and an old template now exceeds the new cap.","solutions":["Flatten the definition so no document is more than 16 levels below the root; move deep levels into sibling branches or separate templates.","Check the definition data programmatically before rendering: compute the maximum children nesting depth and reject/refactor anything above 15 nested levels (root list = level 1).","If the nesting comes from generated data, break cycles in the source data or serialize cyclic references instead of recursive children arrays.","If the limit genuinely blocks a legitimate use, split the tree creation into multiple createDocTree calls targeting different parent documents."],"exampleFix":"// before: 17-level nested children\n{\"title\": \"l0\", \"children\": [{\"title\": \"l1\", \"children\": [ ... l2..l16 ... ]}]}\n// after: split into shallower trees\n{\"title\": \"l0\", \"children\": [{\"title\": \"l1\", \"children\": [{\"title\": \"l2\"}]}]}\n// keep nesting <= 16 levels total","handlingStrategy":"validation","validationCode":"func maxDepth(def any) int {\n    list, ok := def.([]any)\n    if !ok || len(list) == 0 {\n        return 1\n    }\n    d := 1\n    for _, v := range list {\n        m, ok := v.(map[string]any)\n        if !ok { continue }\n        if c, ok := m[\"children\"]; ok {\n            if sub := maxDepth(c) + 1; sub > d { d = sub }\n        }\n    }\n    return d\n}\n// call only if maxDepth(def) <= 16","typeGuard":"func isDocList(v any) bool { _, ok := v.([]any); return ok }","tryCatchPattern":"nodes, err := parseTemplateDocTreeDefinition(def)\nif err != nil {\n    if strings.Contains(err.Error(), \"exceeds the maximum depth\") {\n        // flatten or split the definition, surface a user-facing message\n    }\n    return err\n}","preventionTips":["Cap nesting in whatever generates the definition (generator should stop at 15 nested children).","Break cycles in source data before serializing to a tree definition.","Lint templates for nesting depth as part of template authoring review."],"tags":["template","recursion-limit","validation"],"backgroundTag":"value-out-of-range","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}