siyuan-note/siyuan · error
not query embed block
Error message
not query embed block
What it means
UpdateEmbedBlock updates the content of a query embed block (^(...) block). The library fetches the block tree for the given block ID and verifies that the block's type is actually a block-query-embed node; if the ID points to any other node type (paragraph, heading, etc.), it refuses with "not query embed block". This guards against writing embed-block content onto a normal block.
Solutions
- Verify the block ID actually refers to a query embed block (its .sy node type is NodeBlockQueryEmbed) before calling UpdateEmbedBlock
- Re-fetch the block via the block tree / SQL to confirm its current type; the ID may point to a block whose type changed after edits
- If you intend to update a normal block, use the block update API instead of the embed-block one
Example fix
// before
model.UpdateEmbedBlock(paraBlockID, content) // id is a paragraph block
// after
bt := treenode.GetBlockTree(blockID)
if bt != nil && treenode.TypeAbbr(ast.NodeBlockQueryEmbed.String()) == bt.Type {
model.UpdateEmbedBlock(blockID, content)
} Defensive patterns
Strategy: validation
Validate before calling
const bt = GetBlockTree(blockID)
if (!bt || bt.type !== 'query_embed') throw new Error('block is not a query embed block')
await api.updateEmbedBlock(blockID, content) Type guard
function isQueryEmbedBlock(bt) { return bt != null && bt.type === 'query_embed' } Try / catch
try { await api.updateEmbedBlock(id, content) } catch (e) { if (String(e).includes('not query embed block')) skipNonEmbed(id); else throw e } Prevention
- Resolve embed block IDs via SQL with type filter, not arbitrary block IDs
- Re-fetch block type before each update; IDs can change type after edits
- Log bt.type on failure to diagnose ID mismatches quickly
When it happens
Trigger: Calling UpdateEmbedBlock with an id whose block tree record has a type other than treenode.TypeAbbr(ast.NodeBlockQueryEmbed.String()) — e.g. passing a regular paragraph or heading block ID — produces this error immediately after the ErrBlockNotFound check passes.
Common situations: Frontend passes the wrong block ID when refreshing embed blocks (e.g. the containing block instead of the embed block itself); stale block IDs after a document was edited so the node changed type; plugins calling the embed-block update API with arbitrary block IDs.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/888a9bbbb151d0fc.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/search.go:213
pageCount = (matchedBlockCount + pageSize - 1) / pageSize
return
}
type EmbedBlock struct {
Block *Block `json:"block"`
BlockPaths []*BlockPath `json:"blockPaths"`
AllowChildOperation bool `json:"allowChildOperation"`
}
func UpdateEmbedBlock(id, content string) (err error) {
bt := treenode.GetBlockTree(id)
if nil == bt {
err = ErrBlockNotFound
return
}
if treenode.TypeAbbr(ast.NodeBlockQueryEmbed.String()) != bt.Type {
err = errors.New("not query embed block")
return
}
embedBlock := &EmbedBlock{
Block: &Block{
Markdown: content,
},
}
updateEmbedBlockContent(id, []*EmbedBlock{embedBlock}, bt.BoxID)
return
}
func GetEmbedBlock(embedBlockID string, includeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
return getEmbedBlock(embedBlockID, includeIDs, headingMode, breadcrumb, true, "")
}
func GetEmbedBlockInBox(embedBlockID string, includeIDs []string, headingMode int, breadcrumb bool, boxID string) (ret []*EmbedBlock) {View on GitHub (pinned to 9f775e8a12)