siyuan-note/siyuan · error
code block has no code node
Error message
code block has no code node
What it means
ExportCodeBlock found a node of type ast.NodeCodeBlock but its ChildByType(ast.NodeCodeBlockCode) returned nil, meaning the code block AST is missing the child node that holds the actual code text. This indicates a malformed or unexpectedly structured code block in the tree — an internal invariant violation rather than normal caller error.
Solutions
- Rebuild the tree/index for the document (re-parse the .sy via Lute) and retry.
- Open the block in the editor, re-type or re-create the code block, then export again.
- Restore the document from history/snapshot if the .sy file is corrupted.
- If reproducible from generated input, fix the producer so it emits a NodeCodeBlockCode child.
Defensive patterns
Strategy: try-catch
Validate before calling
node := treenode.GetNodeInTree(tree, blockID)
if node != nil && node.Type == ast.NodeCodeBlock && node.ChildByType(ast.NodeCodeBlockCode) == nil {
return errors.New("malformed code block; rebuild the document index")
} Type guard
func hasCodeChild(node *ast.Node) bool { return node != nil && node.ChildByType(ast.NodeCodeBlockCode) != nil } Try / catch
if err != nil {
if err.Error() == "code block has no code node" {
// trigger doc re-index or restore from history
}
return err
} Prevention
- Avoid hand-building AST nodes in plugins without the NodeCodeBlockCode child
- Restore from snapshots if .sy files show corruption signs
- Keep kernel and lute versions in sync to avoid AST format drift
When it happens
Trigger: Calling ExportCodeBlock on a code block whose serialized .sy tree lost its NodeCodeBlockCode child — e.g. corrupted/partially written .sy file, a tree produced by an older/abnormal format, or a node constructed by a plugin without the code child.
Common situations: Data corruption or interrupted writes to the .sy file; importing or generating documents programmatically with hand-built ASTs; version changes in the lute AST format.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- task list item marker not found
- agent runtime session id mismatch
- attribute view rich text tree is missing
- cannot parse document
- Conf.Language(115)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/cc30e65d7b7b65f2.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/export.go:117
err = withExportReadLockByBlockID(blockID, func() error {
tree, _ := LoadTreeByBlockID(blockID)
if nil == tree {
return ErrBlockNotFound
}
node := treenode.GetNodeInTree(tree, blockID)
if nil == node {
return ErrBlockNotFound
}
if ast.NodeCodeBlock != node.Type {
return errors.New("not a code block")
}
code := node.ChildByType(ast.NodeCodeBlockCode)
if nil == code {
return errors.New("code block has no code node")
}
name := tree.Root.IALAttr("title") + "-" + util.CurrentTimeSecondsStr() + ".txt"
name = util.FilterFileName(name)
exportFolder := filepath.Join(util.TempDir, "export")
// 加密笔记本的导出归入 boxID 子目录,确保 LockBox 清理和服务端校验锁定状态
if IsEncryptedBox(tree.Box) {
exportFolder = filepath.Join(exportFolder, tree.Box)
}
exportFolder = filepath.Join(exportFolder, "code")
if mkdirErr := os.MkdirAll(exportFolder, 0755); mkdirErr != nil {
return mkdirErr
}
code.Tokens = bytes.ReplaceAll(code.Tokens, []byte(editor.Zwj+"```"), []byte("```"))
writePath := filepath.Join(exportFolder, name)
if writeErr := filelock.WriteFile(writePath, code.Tokens); writeErr != nil {View on GitHub (pinned to 9f775e8a12)