siyuan-note/siyuan · error

createDocTree document

Error message

createDocTree document %s must be a string

What it means

The optional template and define fields of a createDocTree document, when present, must be strings. templateDocTreeStringField (called for both keys from parseNodes) type-asserts the value and reports which key failed via the %s placeholder. The key names appear in the message, e.g. "createDocTree document template must be a string".

Solutions

  1. Make the template/define value a string (e.g. a template file name or definition id).
  2. If the value can be absent, remove the key entirely rather than setting null.
  3. Validate field types in the generator before building the definition.

Example fix

// before
{"title": "Doc", "define": {"content": "x"}}
// after
{"title": "Doc", "define": "my-define-id"}
Defensive patterns

Strategy: type-guard

Validate before calling

const validRef = (d) => d.template === undefined || typeof d.template === 'string';

Type guard

const isStringOrAbsent = (v) => v === undefined || typeof v === 'string';

Prevention

When it happens

Trigger: Setting "template" or "define" to a non-string value such as a number, boolean, null, object, or list in a document object of a createDocTree definition.

Common situations: Generator code passing a parsed object under define instead of a name/id; JSON where the template reference was a list of files; null from an unresolved variable.

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


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/efdb81e505eab0b4. Report an issue: GitHub.

Appendix: 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 9f775e8a12)