{"record":{"id":"888a9bbbb151d0fc","repo":"siyuan-note/siyuan","slug":"not-query-embed-block","errorCode":null,"errorMessage":"not query embed block","messagePattern":"not query embed block","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/search.go","lineNumber":206,"sourceCode":"\tpageCount = (matchedBlockCount + pageSize - 1) / pageSize\n\treturn\n}\n\ntype EmbedBlock struct {\n\tBlock               *Block       `json:\"block\"`\n\tBlockPaths          []*BlockPath `json:\"blockPaths\"`\n\tAllowChildOperation bool         `json:\"allowChildOperation\"`\n}\n\nfunc UpdateEmbedBlock(id, content string) (err error) {\n\tbt := treenode.GetBlockTree(id)\n\tif nil == bt {\n\t\terr = ErrBlockNotFound\n\t\treturn\n\t}\n\n\tif treenode.TypeAbbr(ast.NodeBlockQueryEmbed.String()) != bt.Type {\n\t\terr = errors.New(\"not query embed block\")\n\t\treturn\n\t}\n\n\tembedBlock := &EmbedBlock{\n\t\tBlock: &Block{\n\t\t\tMarkdown: content,\n\t\t},\n\t}\n\n\tupdateEmbedBlockContent(id, []*EmbedBlock{embedBlock}, bt.BoxID)\n\treturn\n}\n\nfunc GetEmbedBlock(embedBlockID string, includeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {\n\treturn getEmbedBlock(embedBlockID, includeIDs, headingMode, breadcrumb, true, \"\")\n}\n\nfunc GetEmbedBlockInBox(embedBlockID string, includeIDs []string, headingMode int, breadcrumb bool, boxID string) (ret []*EmbedBlock) {","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/search.go#L188-L224","documentation":"The UpdateEmbedBlock function updates the content of an embed block (NodeBlockQueryEmbed type). It first looks up the block in the block tree, then verifies the block type matches 'NodeBlockQueryEmbed' via treenode.TypeAbbr. If the block ID exists but is a different block type (paragraph, heading, list, etc.), this error is returned. The block type check prevents corrupting non-embed blocks with embed-block-specific update logic.","triggerScenarios":"Calling UpdateEmbedBlock(id, content) where id resolves to a valid block in the block tree, but that block's type is not NodeBlockQueryEmbed. This can happen when a stale or incorrect block ID is passed, or when the embed block was converted to a different block type but the caller still has the old ID.","commonSituations":"Frontend calls UpdateEmbedBlock with a block ID from a stale context (e.g., after the block was converted from embed to another type via the UI). Also occurs when plugins or external API consumers pass arbitrary block IDs without verifying they are embed blocks first. Race conditions where the block type changes between the UI rendering and the update call.","solutions":["Verify the block type is NodeBlockQueryEmbed before calling UpdateEmbedBlock by checking treenode.GetBlockTree(id).Type","Refresh the block ID from the current block tree if the caller's reference may be stale","If the block was intentionally converted to a different type, the update call should be skipped or redirected to the appropriate block-type-specific API"],"exampleFix":"// before\nerr = model.UpdateEmbedBlock(blockID, newContent)\n\n// after\nbt := treenode.GetBlockTree(blockID)\nif bt == nil {\n    return model.ErrBlockNotFound\n}\nif treenode.TypeAbbr(ast.NodeBlockQueryEmbed.String()) != bt.Type {\n    return fmt.Errorf(\"block %s is not an embed block (type: %s)\", blockID, bt.Type)\n}\nerr = model.UpdateEmbedBlock(blockID, newContent)","handlingStrategy":"type-guard","validationCode":"// Verify block is an embed block before updating\nbt := treenode.GetBlockTree(id)\nif bt == nil {\n    return model.ErrBlockNotFound\n}\nif treenode.TypeAbbr(ast.NodeBlockQueryEmbed.String()) != bt.Type {\n    return fmt.Errorf(\"block %s is type %s, not an embed block\", id, bt.Type)\n}","typeGuard":"// Check if a block is an embed block (NodeBlockQueryEmbed)\nfunc isEmbedBlock(id string) bool {\n    bt := treenode.GetBlockTree(id)\n    if bt == nil {\n        return false\n    }\n    return treenode.TypeAbbr(ast.NodeBlockQueryEmbed.String()) == bt.Type\n}","tryCatchPattern":null,"preventionTips":["Always type-check block IDs from user input or stale references before calling type-specific block APIs","Refresh block tree references when the UI context changes (block conversion, deletion, etc.)","Provide a unified block-type-aware dispatch in the frontend rather than calling embed-specific APIs blindly"],"tags":["embed-block","type-mismatch","validation","block-tree"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}