{"record":{"id":"5396663c74ace686","repo":"siyuan-note/siyuan","slug":"createdoctree-document-must-be-a-dictionary","errorCode":null,"errorMessage":"createDocTree document must be a dictionary","messagePattern":"createDocTree document must be a dictionary","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_doc_tree.go","lineNumber":137,"sourceCode":"}\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\")\n\t}\n\n\tnodes := make([]*TemplateDocTreeNode, 0, len(values))\n\tfor _, value := range values {\n\t\tdefinition, ok := value.(map[string]any)\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"createDocTree document must be a dictionary\")\n\t\t}\n\t\tfor key := range definition {\n\t\t\tswitch key {\n\t\t\tcase \"title\", \"template\", \"define\", \"children\":\n\t\t\tdefault:\n\t\t\t\treturn nil, fmt.Errorf(\"createDocTree document contains unknown field [%s]\", key)\n\t\t\t}\n\t\t}\n\n\t\ttitleValue, ok := definition[\"title\"]\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"createDocTree document title is required\")\n\t\t}\n\t\ttitle, ok := titleValue.(string)\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"createDocTree document title must be a string\")\n\t\t}\n\t\ttitle = normalizeDocTitle(title)","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template_doc_tree.go#L119-L155","documentation":"Each entry of a createDocTree list must be a JSON/Go map[string]any object describing one document (with fields title/template/define/children). If an element is a string, number, list, or nil, the type assertion to map fails and this error is thrown.","triggerScenarios":"Writing a definition like [\"Doc A\", \"Doc B\"] (plain strings); an entry that is null; nesting a bare array as an element; YAML that decoded entries into scalars.","commonSituations":"Authors assuming titles alone suffice (list of strings); copy-paste errors leaving a stray null or comma-created element; programmatic generation emitting titles instead of objects; schema drift after editing a template by hand.","solutions":["Convert every list element to an object with at least a title field: [\"Doc A\"] becomes [{\"title\": \"Doc A\"}].","Remove null/empty placeholder entries from the list.","Validate the definition before calling: every element of the top-level list and every children list must be a JSON object.","If titles are stored as strings, map them into objects programmatically before invoking the template action."],"exampleFix":"// before\n[\"Doc A\", \"Doc B\"]\n// after\n[{\"title\": \"Doc A\"}, {\"title\": \"Doc B\"}]","handlingStrategy":"type-guard","validationCode":"for _, v := range list {\n    if _, ok := v.(map[string]any); !ok {\n        return fmt.Errorf(\"every document entry must be an object, got %T\", v)\n    }\n}","typeGuard":"func isDocObject(v any) bool {\n    _, ok := v.(map[string]any)\n    return ok\n}","tryCatchPattern":"nodes, err := parseTemplateDocTreeDefinition(def)\nif err != nil {\n    if strings.Contains(err.Error(), \"must be a dictionary\") {\n        // convert string titles to {\"title\": ...} objects and retry\n    }\n    return err\n}","preventionTips":["Never write bare strings/nulls as list elements in a doc-tree definition.","When converting from a list of names, map each name to an object with a title key.","Validate element types with a schema before rendering."],"tags":["template","type-mismatch","schema"],"backgroundTag":"type-mismatch","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}