{"record":{"id":"dbfe355c7e2ee866","repo":"siyuan-note/siyuan","slug":"createdoctree-definition-must-be-a-list","errorCode":null,"errorMessage":"createDocTree definition must be a list","messagePattern":"createDocTree definition must be a list","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/template_doc_tree.go","lineNumber":127,"sourceCode":"\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\")\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}","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/template_doc_tree.go#L109-L145","documentation":"parseNodes expects the value passed to it (the createDocTree definition, or a node's \"children\" value) to be a JSON/Go []any list. If a string, map, number, or nil is supplied instead, the type assertion fails and this error is thrown. It is a structural schema check on the template's document-tree declaration.","triggerScenarios":"Passing a single object (map) instead of an array as the createDocTree definition; writing children as a single object or a comma-separated string instead of an array; passing the YAML-decoded definition where scalars were expected to be lists.","commonSituations":"Hand-written template JSON where the outermost array is omitted; a children field written as {\"title\": ...} instead of [{\"title\": ...}]; templates migrated from another format that used an object keyed by title; data that YAML/JSON parsed into a scalar for empty/ambiguous values.","solutions":["Wrap the definition in a list: the top-level argument and every children value must be an array of document objects.","Change a single child object children: {title: x} into children: [{title: x}].","Verify the parsed type before calling: ensure json.Unmarshal/YAML decode yields []any (slice) at every list position, not map[string]any or string.","If the definition comes from user input, validate it with a schema validator that enforces array-of-objects at these positions."],"exampleFix":"// before\n{\"title\": \"Parent\", \"children\": {\"title\": \"Child\"}}\n// after\n{\"title\": \"Parent\", \"children\": [{\"title\": \"Child\"}]}","handlingStrategy":"type-guard","validationCode":"if _, ok := def.([]any); !ok {\n    return fmt.Errorf(\"definition must be an array\")\n}\nfor _, v := range def.([]any) {\n    m, ok := v.(map[string]any)\n    if !ok { continue }\n    if c, ok := m[\"children\"]; ok {\n        if _, ok := c.([]any); !ok {\n            return fmt.Errorf(\"children must be an array\")\n        }\n    }\n}","typeGuard":"func isDocDefinition(v any) bool {\n    _, isList := v.([]any)\n    return isList\n}","tryCatchPattern":"nodes, err := parseTemplateDocTreeDefinition(def)\nif err != nil {\n    if strings.Contains(err.Error(), \"must be a list\") {\n        // wrap the value in []any{...} and retry, or report a schema error\n    }\n    return err\n}","preventionTips":["Always author definitions as arrays of objects, never a bare object or string.","Run definitions through a JSON schema validator enforcing type:array at list positions.","Quote YAML values carefully so scalars do not collapse into strings."],"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-14T05:17:10.506Z"}