siyuan-note/siyuan · error

code block has no code node

Error message

code block has no code node

What it means

Returned by ExportCodeBlock when the node IS a NodeCodeBlock but it has no child of type NodeCodeBlockCode. A well-formed code block in SiYuan's AST always contains a code-content child node; its absence indicates a malformed or corrupted tree — the block was created or migrated incorrectly.

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 251596fc0d)

Solutions

  1. Open the document in the SiYuan editor and re-create the code block — the editor will write a well-formed AST.
  2. If the .sy file is hand-edited, ensure the code block node has a child with Type = NodeCodeBlockCode containing the code text in Tokens.
  3. For batch corruption, run the notebook repair/re-index function to rebuild the block tree.
Defensive patterns

Strategy: validation

Try / catch

path, err := model.ExportCodeBlock(blockID)
if err != nil {
    if strings.Contains(err.Error(), "no code node") {
        // malformed AST — guide user to re-create the block
    }
    return err
}

Prevention

When it happens

Trigger: LoadTreeByBlockID returns a tree where the code-block node exists but its child structure is broken (missing NodeCodeBlockCode child). Happens with hand-edited .sy files, buggy import/migration, or partial sync data.

Common situations: Imported a Markdown file that produced a partial code-block node. Sync conflict resolution dropped the code-content child. Manual editing of the .sy JSON damaged the tree structure. A very old SiYuan version created the block with a different child layout.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/cc30e65d7b7b65f2. Report an issue: GitHub.