{"record":{"id":"e3f2cab7af01efa6","repo":"siyuan-note/siyuan","slug":"createdoctree-requires-at-least-one-document","errorCode":null,"errorMessage":"createDocTree requires at least one document","messagePattern":"createDocTree requires at least one document","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_doc_tree.go","lineNumber":112,"sourceCode":"\tnodes         []*TemplateDocTreeNode\n\tenabled       bool\n\tallowCreation bool\n\ttotalOutput   int\n}\n\nvar (\n\ttemplateDocTreePlans     sync.Map\n\ttemplateDocTreePlansLock sync.Mutex\n)\n\nfunc parseTemplateDocTreeDefinition(def any) ([]*TemplateDocTreeNode, error) {\n\tstate := &templateDocTreeParseState{}\n\tnodes, err := state.parseNodes(def, 1)\n\tif nil != err {\n\t\treturn nil, err\n\t}\n\tif 0 == len(nodes) {\n\t\treturn nil, errors.New(\"createDocTree requires at least one document\")\n\t}\n\treturn nodes, nil\n}\n\ntype templateDocTreeParseState struct {\n\tcount int\n}\n\nfunc (state *templateDocTreeParseState) parseNodes(value any, depth int) ([]*TemplateDocTreeNode, error) {\n\tif maxTemplateDocTreeDepth < depth {\n\t\treturn nil, fmt.Errorf(\"createDocTree exceeds the maximum depth of %d\", maxTemplateDocTreeDepth)\n\t}\n\tvalues, ok := value.([]any)\n\tif !ok {\n\t\treturn nil, errors.New(\"createDocTree definition must be a list\")\n\t}\n\tif 0 == len(values) {\n\t\treturn nil, errors.New(\"createDocTree document list must not be empty\")","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template_doc_tree.go#L94-L130","documentation":"parseTemplateDocTreeDefinition parses the createDocTree definition block inside a template and requires it to produce at least one document node. If the parsed node list is empty, it fails with this error, preventing creation of a zero-document tree. Callers include the collector's create function and unit tests.","triggerScenarios":"A template calling .action{createDocTree ...} whose definition block contains no document entries — empty body, only comments/blank lines, or entries that all failed to parse upstream (though those usually return their own error).","commonSituations":"Manually emptying a createDocTree definition while keeping the call; copy-pasting a template skeleton with the document list removed; template-generation code emitting an empty definition.","solutions":["Add at least one document entry to the createDocTree definition block in the template.","If the tree is intentionally empty, remove the .action{createDocTree ...} call entirely.","Check that document entries are not commented out or misplaced outside the definition block."],"exampleFix":"<!-- before -->\n.action{createDocTree \"\"}\n<!-- after -->\n.action{createDocTree \"doc1\"}\n- content of doc1","handlingStrategy":"validation","validationCode":"// Ensure the createDocTree definition contains at least one document entry before rendering\nif (!/-\\s+\\S/.test(extractCreateDocTreeBlock(md))) {\n  throw new Error(\"createDocTree definition has no documents\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  await renderTemplate(p);\n} catch (e) {\n  if (String(e).includes(\"requires at least one document\")) {\n    console.error(\"Add a document entry to the createDocTree definition or remove the call\");\n  }\n  throw e;\n}","preventionTips":["Never leave a createDocTree definition block empty","Keep at least one '- title' entry under the createDocTree call","Preview doc-tree templates before creating documents"],"tags":["template","createdoctree","empty-input"],"backgroundTag":"empty-required-field","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}