siyuan-note/siyuan · error
createDocTree document template and define are mutually excl
Error message
createDocTree document template and define are mutually exclusive
What it means
A createDocTree document may specify how its content is produced either by referencing an existing template file (template) or by an inline define block, but not both. Supplying both non-empty template and define fields is ambiguous and rejected by parseNodes.
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 8641553a1f)
Solutions
- Keep only one content source: delete the template field to use the inline define, or delete define to use the template file.
- If both behaviors are wanted, nest documents: one child with template and a sibling child with define.
- In generated definitions, emit template XOR define based on which source is available.
- Pre-validate: reject any node where both fields are non-empty strings before rendering.
Example fix
// before
{"title": "Daily", "template": "daily.md", "define": "content here"}
// after (use define)
{"title": "Daily", "define": "content here"} Defensive patterns
Strategy: validation
Validate before calling
var walk func(nodes []any) error
walk = func(nodes []any) error {
for _, v := range nodes {
m, ok := v.(map[string]any)
if !ok { continue }
tpl, _ := m["template"].(string)
def, _ := m["define"].(string)
if tpl != "" && def != "" {
return errors.New("template and define are mutually exclusive on one document")
}
if c, ok := m["children"]; ok {
if cl, ok := c.([]any); ok {
if err := walk(cl); err != nil { return err }
}
}
}
return nil
} Type guard
func hasOneContentSource(v any) bool {
m, ok := v.(map[string]any)
if !ok { return false }
tpl, _ := m["template"].(string)
def, _ := m["define"].(string)
return tpl == "" || def == ""
} Try / catch
nodes, err := parseTemplateDocTreeDefinition(def)
if err != nil {
if strings.Contains(err.Error(), "mutually exclusive") {
// drop template or define on the offending node and retry
}
return err
} Prevention
- Pick one content mechanism per document: file template OR inline define.
- In generators, emit template XOR define based on availability.
- When converting a template-based entry to inline content, delete the template field in the same edit.
When it happens
Trigger: A document object like {"title": "X", "template": "note.md", "define": "..."}; merging two definition styles when refactoring; copy-pasting fields from two different example documents into one.
Common situations: Authors unsure of the two mechanisms adding both to be safe; generated definitions that always emit both keys with defaults; editing a template-based entry to inline content while forgetting to delete the template field.
Related errors
- path is required
- attribute view [%s] has no available visible view
- invalid content template path
- createDocTree exceeds the maximum depth of %d
- createDocTree document list must not be empty
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/6683fa34f3943804.
Report an issue: GitHub.