siyuan-note/siyuan · error

query embed block statement not found

Error message

query embed block statement not found

What it means

After loading the tree for a verified embed block, GetQueryEmbedStatement locates the node and then its child NodeBlockQueryEmbedScript holding the SQL statement. If the node is missing or the script child node is absent, the embed block is structurally malformed and the library errors with "query embed block statement not found". This indicates internal data corruption rather than a bad argument.

Solutions

  1. Re-open the embed block in the editor and re-enter the SQL statement so the script child node is rewritten
  2. Check the .sy file content and restore the {{...}} script section of the embed block
  3. Restore the document from data history/snapshot if the embed node is corrupted
Defensive patterns

Strategy: try-catch

Validate before calling

const bt = GetBlockTree(id)
if (!bt || bt.type !== 'query_embed') return null
// no client-side way to inspect the script child node; treat parse failure as corrupt data

Try / catch

try { return api.getQueryEmbedStatement(id) } catch (e) { if (String(e).includes('statement not found')) { reportCorruptEmbed(id); return null } throw e }

Prevention

When it happens

Trigger: Calling GetQueryEmbedStatement on an embed block whose tree contains a NodeBlockQueryEmbed node but no NodeBlockQueryEmbedScript child — e.g. the .sy file was hand-edited, truncated, or produced by a version that serialized the embed node without its script child.

Common situations: Documents edited by older/custom tooling or third-party sync that wrote malformed embed nodes; partially-written .sy files after a crash; manual XML editing of the .sy file that dropped the script child.

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


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

Appendix: source

Thrown at kernel/model/search.go:312

	}
	if treenode.TypeAbbr(ast.NodeBlockQueryEmbed.String()) != bt.Type {
		err = errors.New("not query embed block")
		return
	}

	tree, loadErr := filesys.LoadTree(bt.BoxID, bt.Path, util.NewLute())
	if nil != loadErr {
		err = loadErr
		return
	}
	node := treenode.GetNodeInTree(tree, embedBlockID)
	if nil == node || ast.NodeBlockQueryEmbed != node.Type {
		err = ErrBlockNotFound
		return
	}
	scriptNode := node.ChildByType(ast.NodeBlockQueryEmbedScript)
	if nil == scriptNode {
		err = errors.New("query embed block statement not found")
		return
	}

	stmt = stdhtml.UnescapeString(scriptNode.TokensStr())
	stmt = strings.ReplaceAll(stmt, editor.IALValEscNewLine, "\n")
	boxID = bt.BoxID
	return
}

func SearchEmbedBlock(embedBlockID, stmt string, excludeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
	return SearchEmbedBlockInBox(embedBlockID, stmt, excludeIDs, headingMode, breadcrumb, "")
}

// SearchEmbedBlockInBox 与 SearchEmbedBlock 一致,但按 boxID 路由 SQL 到加密 content db。
// 加密笔记本的嵌入块查询走独立加密库(全局 siyuan.db 不含加密数据),boxID 为空时落回全局库。
func SearchEmbedBlockInBox(embedBlockID, stmt string, excludeIDs []string, headingMode int, breadcrumb bool, boxID string) (ret []*EmbedBlock) {
	return searchEmbedBlockInBox(embedBlockID, stmt, excludeIDs, headingMode, breadcrumb, boxID, true)
}

View on GitHub (pinned to 9f775e8a12)