siyuan-note/siyuan · error
createDocTree exceeds the maximum depth of %d
Error message
createDocTree exceeds the maximum depth of %d
What it means
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.
Source
Thrown at kernel/model/template_doc_tree.go:123
func parseTemplateDocTreeDefinition(def any) ([]*TemplateDocTreeNode, error) {
state := &templateDocTreeParseState{}
nodes, err := state.parseNodes(def, 1)
if nil != err {
return nil, err
}
if 0 == len(nodes) {
return nil, errors.New("createDocTree requires at least one document")
}
return nodes, nil
}
type templateDocTreeParseState struct {
count int
}
func (state *templateDocTreeParseState) parseNodes(value any, depth int) ([]*TemplateDocTreeNode, error) {
if maxTemplateDocTreeDepth < depth {
return nil, fmt.Errorf("createDocTree exceeds the maximum depth of %d", maxTemplateDocTreeDepth)
}
values, ok := value.([]any)
if !ok {
return nil, errors.New("createDocTree definition must be a list")
}
if 0 == len(values) {
return nil, errors.New("createDocTree document list must not be empty")
}
nodes := make([]*TemplateDocTreeNode, 0, len(values))
for _, value := range values {
definition, ok := value.(map[string]any)
if !ok {
return nil, errors.New("createDocTree document must be a dictionary")
}
for key := range definition {
switch key {
case "title", "template", "define", "children":View on GitHub (pinned to 8641553a1f)
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.
Example fix
// before: 17-level nested children
{"title": "l0", "children": [{"title": "l1", "children": [ ... l2..l16 ... ]}]}
// after: split into shallower trees
{"title": "l0", "children": [{"title": "l1", "children": [{"title": "l2"}]}]}
// keep nesting <= 16 levels total Defensive patterns
Strategy: validation
Validate before calling
func maxDepth(def any) int {
list, ok := def.([]any)
if !ok || len(list) == 0 {
return 1
}
d := 1
for _, v := range list {
m, ok := v.(map[string]any)
if !ok { continue }
if c, ok := m["children"]; ok {
if sub := maxDepth(c) + 1; sub > d { d = sub }
}
}
return d
}
// call only if maxDepth(def) <= 16 Type guard
func isDocList(v any) bool { _, ok := v.([]any); return ok } Try / catch
nodes, err := parseTemplateDocTreeDefinition(def)
if err != nil {
if strings.Contains(err.Error(), "exceeds the maximum depth") {
// flatten or split the definition, surface a user-facing message
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- ErrFilterTooDeep
- path is required
- attribute view [%s] has no available visible view
- invalid content template path
- createDocTree document list must not be empty
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/4cec3822c85b360d.
Report an issue: GitHub.