siyuan-note/siyuan · error

createDocTree document template and define are mutually…

Error message

createDocTree document template and define are mutually exclusive

What it means

A createDocTree document may specify either a template file (template) or a template definition (define), never both. If templateDocTreeStringField returns non-empty values for both keys, parseNodes rejects the entry because the two content sources would conflict.

Solutions

  1. Remove the "define" field and keep only "template" (or vice versa).
  2. Decide which content source the document should use and delete the other key.
  3. Search templates for entries that set both fields and clean them up.

Example fix

// before
{"title": "Doc", "template": "a.md", "define": "b"}
// after
{"title": "Doc", "template": "a.md"}
Defensive patterns

Strategy: validation

Validate before calling

const exclusive = (d) => !(d.template && d.define);
if (!docs.every(exclusive)) throw new Error('template and define are mutually exclusive');

Prevention

When it happens

Trigger: A document object containing both non-empty "template" and "define" fields, e.g. {"title": "Doc", "template": "a.md", "define": "b"}. Raised from parseTemplateDocTreeDefinition during editor template insertion.

Common situations: Merging two template snippets that each used one of the fields; leaving a default define value in place while adding a template reference; refactoring templates from one mechanism to the other without removing the old key.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/6683fa34f3943804. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/template_doc_tree.go:172

		}
		title = normalizeDocTitle(title)
		if "" == title {
			return nil, errors.New("createDocTree document title must not be empty")
		}
		if 512 < utf8.RuneCountInString(title) {
			return nil, fmt.Errorf("createDocTree document title exceeds %d characters", 512)
		}

		templateName, err := templateDocTreeStringField(definition, "template")
		if nil != err {
			return nil, err
		}
		defineName, err := templateDocTreeStringField(definition, "define")
		if nil != err {
			return nil, err
		}
		if "" != templateName && "" != defineName {
			return nil, errors.New("createDocTree document template and define are mutually exclusive")
		}

		state.count++
		if maxTemplateDocTreeDocs < state.count {
			return nil, fmt.Errorf("createDocTree exceeds the maximum document count of %d", maxTemplateDocTreeDocs)
		}
		id := ast.NewNodeID()
		node := &TemplateDocTreeNode{
			ID:       id,
			RootID:   id,
			Title:    title,
			Depth:    depth,
			Template: templateName,
			Define:   defineName,
		}
		if childrenValue, exists := definition["children"]; exists {
			children, parseErr := state.parseNodes(childrenValue, depth+1)
			if nil != parseErr {

View on GitHub (pinned to 9f775e8a12)