siyuan-note/siyuan · error

createDocTree document list must not be empty

Error message

createDocTree document list must not be empty

What it means

An empty list was supplied where parseNodes expected at least one document definition. Either the top-level createDocTree array is empty or a children array is empty ([]). Because an empty list can never produce a document, the parser rejects it immediately.

Source

Thrown at kernel/model/template_doc_tree.go:130

		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":
			default:
				return nil, fmt.Errorf("createDocTree document contains unknown field [%s]", key)
			}
		}

		titleValue, ok := definition["title"]
		if !ok {

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Remove the empty children key from the document definition, or populate it with at least one child object.
  2. If the top-level list is empty, add at least one document definition; parseTemplateDocTreeDefinition also enforces "at least one document".
  3. Check the upstream data source/conditionals that produced an empty list and guard the createDocTree call on non-empty data.
  4. Render-time: if children may be empty, build the definition conditionally so the children key is omitted entirely.

Example fix

// before
{"title": "Parent", "children": []}
// after (omit children)
{"title": "Parent"}
Defensive patterns

Strategy: validation

Validate before calling

list, ok := def.([]any)
if !ok || len(list) == 0 {
    return errors.New("definition must be a non-empty array")
}
var walk func(nodes []any) error
walk = func(nodes []any) error {
    for _, v := range nodes {
        m, _ := v.(map[string]any)
        if m == nil { continue }
        if c, ok := m["children"]; ok {
            cl, ok := c.([]any)
            if !ok || len(cl) == 0 {
                return errors.New("children must be a non-empty array; omit the key instead")
            }
            if err := walk(cl); err != nil { return err }
        }
    }
    return nil
}
if err := walk(list); err != nil { return err }

Type guard

func nonEmptyList(v any) bool {
    l, ok := v.([]any)
    return ok && len(l) > 0
}

Try / catch

nodes, err := parseTemplateDocTreeDefinition(def)
if err != nil {
    if strings.Contains(err.Error(), "must not be empty") {
        // drop empty children keys or abort with a clear user message
    }
    return err
}

Prevention

When it happens

Trigger: Calling createDocTree with definition []; providing children: [] on a document node; a filter/template step that strips all entries from the list before rendering.

Common situations: Generated templates where the data source returned no rows; a template author leaving children: [] as a placeholder; variables interpolating to empty arrays at render time; copying a template and deleting all child entries but keeping the empty children key.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/352a8c51cfe08923. Report an issue: GitHub.