{"record":{"id":"459079fe9290c9d3","repo":"siyuan-note/siyuan","slug":"createdoctree-is-only-available-when-manually-inse","errorCode":null,"errorMessage":"createDocTree is only available when manually inserting a template in the editor","messagePattern":"createDocTree is only available when manually inserting a template in the editor","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_doc_tree.go","lineNumber":218,"sourceCode":"func 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\n}\n\nfunc (collector *templateDocTreeCollector) bindNodes(nodes []*TemplateDocTreeNode, parentID, parentPath, parentHPath string) {\n\tfor _, node := range nodes {\n\t\tnode.ParentID = parentID\n\t\tnode.path = strings.TrimSuffix(parentPath, \".sy\") + \"/\" + node.ID + \".sy\"\n\t\tnode.HPath = path.Join(parentHPath, node.Title)","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template_doc_tree.go#L200-L236","documentation":"The createDocTree template action may only run inside a collector that is both enabled and flagged allowCreation, which the kernel sets only when a user manually inserts a template into the editor. When create() is invoked in any other context (not enabled, or enabled for preview/render only), it refuses with this error. This prevents templates from creating documents during passive renders such as previews or template listing.","triggerScenarios":"Invoking the template's createDocTree function during template preview (TemplateRenderModePreview), content rendering, or from a code path where the collector was constructed with allowCreation=false — e.g. calling the collector directly in tests or from non-editor-insert render flows.","commonSituations":"Developers testing a template that calls createDocTree and running it through the preview path; plugin/integration code reusing the render pipeline to execute templates; automated tests calling create() without simulating an editor insert.","solutions":["Use the editor's manual template insert (insert template via the editor UI) so the kernel enables allowCreation.","In tests, construct the collector with enabled=true and allowCreation=true (as the editor-insert path does).","If you only need the parsed structure, call parseTemplateDocTreeDefinition directly instead of create()."],"exampleFix":"// before (test)\nc := &templateDocTreeCollector{}\nc.create(def) // enabled=false\n// after\nc := &templateDocTreeCollector{enabled: true, allowCreation: true, rootID: ..., rootPath: ..., rootHPath: ...}\nc.create(def)","handlingStrategy":"try-catch","validationCode":"// only call createDocTree in flows that go through manual editor template insert\nconst canCreate = renderMode === \"editorInsert\";","typeGuard":null,"tryCatchPattern":"try {\n  collector.create(def);\n} catch (e) {\n  if (String(e).includes(\"only available when manually inserting\")) {\n    // fall back to preview-only rendering or re-run via editor insert\n  }\n}","preventionTips":["Only exercise createDocTree via manual template insertion in the editor","Do not reuse the render pipeline for doc-creating templates in previews or plugins","In tests, enable the collector with allowCreation=true to mirror the editor path"],"tags":["template","permission","render-context"],"backgroundTag":"operation-not-supported","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"}