siyuan-note/siyuan · error

createDocTree document %s must not be empty

Error message

createDocTree document %s must not be empty

What it means

After confirming the "template" or "define" field is a string, the parser trims whitespace and rejects it if the result is empty. A key present with an empty or whitespace-only string value is treated as invalid rather than as absent, so createDocTree parsing fails with "createDocTree document <key> must not be empty".

Source

Thrown at kernel/model/template_doc_tree.go:211

			node.Children = children
		}
		nodes = append(nodes, node)
	}
	return nodes, nil
}

func templateDocTreeStringField(definition map[string]any, key string) (string, error) {
	value, exists := definition[key]
	if !exists {
		return "", nil
	}
	ret, ok := value.(string)
	if !ok {
		return "", fmt.Errorf("createDocTree document %s must be a string", key)
	}
	ret = strings.TrimSpace(ret)
	if "" == ret {
		return "", fmt.Errorf("createDocTree document %s must not be empty", key)
	}
	return ret, nil
}

func (collector *templateDocTreeCollector) create(def any) (string, error) {
	if !collector.enabled || !collector.allowCreation {
		return "", errors.New("createDocTree is only available when manually inserting a template in the editor")
	}
	nodes, err := parseTemplateDocTreeDefinition(def)
	if nil != err {
		return "", err
	}
	if maxTemplateDocTreeDocs < len(flattenTemplateDocTreeNodes0(collector.nodes))+len(flattenTemplateDocTreeNodes0(nodes)) {
		return "", fmt.Errorf("createDocTree exceeds the maximum document count of %d", maxTemplateDocTreeDocs)
	}
	collector.bindNodes(nodes, collector.rootID, collector.rootPath, collector.rootHPath)
	collector.nodes = append(collector.nodes, nodes...)
	return "", nil

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Provide a real template/define name, or delete the key entirely when it is not needed.
  2. If the value comes from a variable, guard it: only emit the field when the variable is non-empty.
  3. Trim inputs before building the definition and omit empty fields.

Example fix

// before
{"title":"Child","define":""}
// after
{"title":"Child","define":"my-define"}  // or remove the define key
Defensive patterns

Strategy: validation

Validate before calling

for (const doc of definition) {
  for (const key of ["template", "define"]) {
    if (key in doc && typeof doc[key] === "string" && doc[key].trim() === "") throw new Error(`${key} must not be empty`);
  }
}

Type guard

const hasValue = (v) => typeof v === "string" && v.trim().length > 0;

Try / catch

try {
  render(def);
} catch (e) {
  if (/must not be empty/.test(String(e))) {
    // remove the empty key or supply a real value
  }
}

Prevention

When it happens

Trigger: A createDocTree document entry such as {"title":"x","template":""}, {"title":"x","define":" "}, or a value built by string concatenation/interpolation that resolved to empty.

Common situations: Template variables that expanded to nothing (e.g. ."" . $name with an unset variable), copy-pasted entries with the value deleted, or form-generated JSON where empty inputs were serialized as "" instead of omitted.

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/23a9f7bf16bcb788. Report an issue: GitHub.