siyuan-note/siyuan · error
invalid template document attributes
Error message
invalid template document attributes
What it means
A fenced code block marked with the siyuan-template-doc-attrs-v1 marker was found but has no code body node. The document-attributes block is malformed: the fence info marker exists but the NodeCodeBlockCode child is missing, so the attribute payload cannot be extracted.
Source
Thrown at kernel/model/template_export_attrs.go:51
if tree == nil {
return nil, errors.New("parse template tree failed")
}
normalizeTree(tree)
if err := applyTemplateDocumentAttributes(tree); err != nil {
return nil, err
}
return tree, nil
}
// 独立文档属性保留在原位置求值,渲染完成后再合并到根节点。
func applyTemplateDocumentAttributes(tree *parse.Tree) error {
for node := tree.Root.FirstChild; node != nil; {
next := node.Next
info := node.ChildByType(ast.NodeCodeBlockFenceInfoMarker)
if node.Type == ast.NodeCodeBlock && info != nil && string(info.CodeBlockInfo) == templateDocumentAttributeMarker {
code := node.ChildByType(ast.NodeCodeBlockCode)
if code == nil {
return errors.New("invalid template document attributes")
}
source := strings.TrimSpace(string(code.Tokens))
attrs := parseTemplateDocumentAttributes(source)
if len(attrs) == 0 {
return errors.New("invalid template document attributes")
}
for _, attr := range attrs {
if attr[0] == "id" || attr[0] == "updated" {
continue
}
tree.Root.RemoveIALAttr(attr[0])
tree.Root.KramdownIAL = append(tree.Root.KramdownIAL, attr)
}
if next != nil && next.Type == ast.NodeKramdownBlockIAL && parse.IAL2Map(parse.Tokens2IAL(next.Tokens))["type"] != "doc" {
ial := next
next = next.Next
ial.Unlink()
}View on GitHub (pinned to 8641553a1f)
Solutions
- Add the attribute payload body inside the marker code block, or remove the marker code block entirely
- Use the app's save-as-template flow to regenerate a well-formed attributes block
- Do not hand-edit the siyuan-template-doc-attrs-v1 fence
Example fix
// before ```siyuan-template-doc-attrs-v1 ``` // after (either fill the body or remove the block) ```siyuan-template-doc-attrs-v1 name: my-template ```
Defensive patterns
Strategy: validation
Validate before calling
// ensure the marker fence has a non-empty body before parsing
if strings.Contains(string(md), "siyuan-template-doc-attrs-v1") {
var inBlock, hasBody bool
for _, line := range strings.Split(string(md), "\n") {
if strings.HasPrefix(strings.TrimSpace(line), "```siyuan-template-doc-attrs-v1") { inBlock = true; continue }
if inBlock && strings.TrimSpace(line) == "```" { break }
if inBlock && strings.TrimSpace(line) != "" { hasBody = true }
}
if !hasBody { return errors.New("doc-attrs fence has no body") }
} Try / catch
if err := applyTemplateDocumentAttributes(tree); err != nil {
return fmt.Errorf("fix or remove the siyuan-template-doc-attrs-v1 block: %w", err)
} Prevention
- Never hand-edit the siyuan-template-doc-attrs-v1 fence
- Regenerate templates via the app's save-as-template flow
- Keep the fence body non-empty whenever the marker is present
When it happens
Trigger: applyTemplateDocumentAttributes encounters a code block whose info marker equals templateDocumentAttributeMarker but ChildByType(ast.NodeCodeBlockCode) returns nil — e.g. an empty or hand-edited fence block. Called via parseTemplateKTree from renderTemplateSource and renderTemplateDocTreeMarkdown.
Common situations: Hand-editing a template and leaving the marker fence without a body; a tool stripped the code content but kept the info marker; copy/paste lost the fenced body.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- path is required
- attribute view [%s] has no available visible view
- invalid content template path
- createDocTree exceeds the maximum depth of %d
- createDocTree document list must not be empty
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/ea01670c060218fe.
Report an issue: GitHub.