{"record":{"id":"23a9f7bf16bcb788","repo":"siyuan-note/siyuan","slug":"createdoctree-document-s-must-not-be-empty","errorCode":null,"errorMessage":"createDocTree document %s must not be empty","messagePattern":"createDocTree document (.+?) must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_doc_tree.go","lineNumber":211,"sourceCode":"\t\t\tnode.Children = children\n\t\t}\n\t\tnodes = append(nodes, node)\n\t}\n\treturn nodes, nil\n}\n\nfunc templateDocTreeStringField(definition map[string]any, key string) (string, error) {\n\tvalue, exists := definition[key]\n\tif !exists {\n\t\treturn \"\", nil\n\t}\n\tret, ok := value.(string)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"createDocTree document %s must be a string\", key)\n\t}\n\tret = strings.TrimSpace(ret)\n\tif \"\" == ret {\n\t\treturn \"\", fmt.Errorf(\"createDocTree document %s must not be empty\", key)\n\t}\n\treturn ret, nil\n}\n\nfunc (collector *templateDocTreeCollector) create(def any) (string, error) {\n\tif !collector.enabled || !collector.allowCreation {\n\t\treturn \"\", errors.New(\"createDocTree is only available when manually inserting a template in the editor\")\n\t}\n\tnodes, err := parseTemplateDocTreeDefinition(def)\n\tif nil != err {\n\t\treturn \"\", err\n\t}\n\tif maxTemplateDocTreeDocs < len(flattenTemplateDocTreeNodes0(collector.nodes))+len(flattenTemplateDocTreeNodes0(nodes)) {\n\t\treturn \"\", fmt.Errorf(\"createDocTree exceeds the maximum document count of %d\", maxTemplateDocTreeDocs)\n\t}\n\tcollector.bindNodes(nodes, collector.rootID, collector.rootPath, collector.rootHPath)\n\tcollector.nodes = append(collector.nodes, nodes...)\n\treturn \"\", nil","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/template_doc_tree.go#L193-L229","documentation":"If the template or define field of a createDocTree document is present but trims to an empty string, templateDocTreeStringField rejects it. An explicitly present-but-blank content reference is treated as a mistake rather than ignored, so users are not silently given a document with no content source.","triggerScenarios":"Passing \"template\": \"\" or \"define\": \"   \" (whitespace only) in a document object. The key exists, so the missing-field path is skipped, but the trimmed value is empty. Raised from parseNodes via parseTemplateDocTreeDefinition.","commonSituations":"Template variables that resolve to empty strings; generator code initializing fields to \"\" instead of omitting them; user-cleared input in a template builder UI serialized as an empty key.","solutions":["Remove the template/define key entirely when no content source is intended.","Fill in an actual template file name or define id.","In generator code, omit empty fields instead of serializing empty strings.","Trim and filter empty values before building the definition object."],"exampleFix":"// before\n{\"title\": \"Doc\", \"template\": \"\"}\n// after\n{\"title\": \"Doc\"}","handlingStrategy":"validation","validationCode":"function cleanDoc(d) {\n  for (const k of ['template', 'define']) {\n    if (typeof d[k] === 'string' && d[k].trim() === '') delete d[k];\n  }\n  return d;\n}\ndocs = docs.map(cleanDoc);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Omit keys instead of writing empty strings.","Trim optional string fields and drop them when blank.","Ensure template variables in these fields never resolve to empty."],"tags":["template","validation","empty-value"],"backgroundTag":"empty-required-field","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}