siyuan-note/siyuan · error
createDocTree document must be a dictionary
Error message
createDocTree document must be a dictionary
What it means
Each entry of a createDocTree list must be a JSON/Go map[string]any object describing one document (with fields title/template/define/children). If an element is a string, number, list, or nil, the type assertion to map fails and this error is thrown.
Source
Thrown at kernel/model/template_doc_tree.go:137
}
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":
default:
return nil, fmt.Errorf("createDocTree document contains unknown field [%s]", key)
}
}
titleValue, ok := definition["title"]
if !ok {
return nil, errors.New("createDocTree document title is required")
}
title, ok := titleValue.(string)
if !ok {
return nil, errors.New("createDocTree document title must be a string")
}
title = normalizeDocTitle(title)View on GitHub (pinned to 8641553a1f)
Solutions
- Convert every list element to an object with at least a title field: ["Doc A"] becomes [{"title": "Doc A"}].
- Remove null/empty placeholder entries from the list.
- Validate the definition before calling: every element of the top-level list and every children list must be a JSON object.
- If titles are stored as strings, map them into objects programmatically before invoking the template action.
Example fix
// before
["Doc A", "Doc B"]
// after
[{"title": "Doc A"}, {"title": "Doc B"}] Defensive patterns
Strategy: type-guard
Validate before calling
for _, v := range list {
if _, ok := v.(map[string]any); !ok {
return fmt.Errorf("every document entry must be an object, got %T", v)
}
} Type guard
func isDocObject(v any) bool {
_, ok := v.(map[string]any)
return ok
} Try / catch
nodes, err := parseTemplateDocTreeDefinition(def)
if err != nil {
if strings.Contains(err.Error(), "must be a dictionary") {
// convert string titles to {"title": ...} objects and retry
}
return err
} Prevention
- Never write bare strings/nulls as list elements in a doc-tree definition.
- When converting from a list of names, map each name to an object with a title key.
- Validate element types with a schema before rendering.
When it happens
Trigger: Writing a definition like ["Doc A", "Doc B"] (plain strings); an entry that is null; nesting a bare array as an element; YAML that decoded entries into scalars.
Common situations: Authors assuming titles alone suffice (list of strings); copy-paste errors leaving a stray null or comma-created element; programmatic generation emitting titles instead of objects; schema drift after editing a template by hand.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- createDocTree definition must be a list
- property %q: x-mcp-header can only be applied to primitive t
- new item template field [%s] current time value is invalid
- new item template field [%s] value is invalid
- createDocTree document contains unknown field [%s]
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/5396663c74ace686.
Report an issue: GitHub.