siyuan-note/siyuan · error
createDocTree document %s must be a string
Error message
createDocTree document %s must be a string
What it means
templateDocTreeStringField validates the optional "template" or "define" field of a createDocTree document entry. If the key exists but its value is not a JSON string (e.g. a number, boolean, object, or array), parsing fails with "createDocTree document <key> must be a string". The parser is strict because both fields are later resolved to template file names.
Source
Thrown at kernel/model/template_doc_tree.go:207
children, parseErr := state.parseNodes(childrenValue, depth+1)
if nil != parseErr {
return nil, parseErr
}
node.Children = children
}
nodes = append(nodes, node)
}
return nodes, nil
}
func templateDocTreeStringField(definition map[string]any, key string) (string, error) {
value, exists := definition[key]
if !exists {
return "", nil
}
ret, ok := value.(string)
if !ok {
return "", fmt.Errorf("createDocTree document %s must be a string", key)
}
ret = strings.TrimSpace(ret)
if "" == ret {
return "", fmt.Errorf("createDocTree document %s must not be empty", key)
}
return ret, nil
}
func (collector *templateDocTreeCollector) create(def any) (string, error) {
if !collector.enabled || !collector.allowCreation {
return "", errors.New("createDocTree is only available when manually inserting a template in the editor")
}
nodes, err := parseTemplateDocTreeDefinition(def)
if nil != err {
return "", err
}
if maxTemplateDocTreeDocs < len(flattenTemplateDocTreeNodes0(collector.nodes))+len(flattenTemplateDocTreeNodes0(nodes)) {
return "", fmt.Errorf("createDocTree exceeds the maximum document count of %d", maxTemplateDocTreeDocs)View on GitHub (pinned to 8641553a1f)
Solutions
- Quote the value: change "template": 123 to "template": "123".
- Remove the field entirely if no child template/define is needed (absent keys are allowed).
- If generated by code, coerce the value to a string before building the definition (e.g. str(value)).
Example fix
// before
{"title":"Child","template":42}
// after
{"title":"Child","template":"child-template"} Defensive patterns
Strategy: validation
Validate before calling
for (const doc of definition) {
for (const key of ["template", "define"]) {
if (key in doc && typeof doc[key] !== "string") throw new Error(`${key} must be a string`);
}
} Type guard
const isNonEmptyString = (v) => typeof v === "string" && v.trim().length > 0;
Try / catch
try {
render(def);
} catch (e) {
if (/must be a string/.test(String(e))) {
// fix the offending field type in the definition
}
} Prevention
- Always quote template/define values in template syntax
- Validate generated JSON types before calling the render pipeline
- Omit optional fields instead of passing non-string placeholders
When it happens
Trigger: A createDocTree document entry like {"title":"x","template":123}, {"title":"x","define":true}, or {"template":{...}} passed to the collector's create() or rendered via parseTemplateDocTreeDefinition.
Common situations: Hand-writing template syntax with an unquoted value, JSON produced by a script using non-string types, or copying a doc entry where the field was set programmatically to a number/null.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- path is required
- new item template field [%s] current time value is invalid
- new item template field [%s] value is invalid
- attribute view [%s] has no available visible view
- invalid content template path
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/efdb81e505eab0b4.
Report an issue: GitHub.