{"record":{"id":"9b5fcfe33b85f7ce","repo":"siyuan-note/siyuan","slug":"content-block-with-id-s-not-found","errorCode":null,"errorMessage":"Content block with id [%s] not found","messagePattern":"Content block with id \\[(.+?)\\] not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/block.go","lineNumber":843,"sourceCode":"\tif !sameTree {\n\t\tif err = indexWriteTreeUpsertQueue(defTree); err != nil {\n\t\t\treturn\n\t\t}\n\t}\n\tFlushTxQueue()\n\tutil.ReloadUI()\n\treturn\n}\n\nfunc GetHeadingDeleteTransaction(id string) (transaction *Transaction, err error) {\n\ttree, err := LoadTreeByBlockID(id)\n\tif err != nil {\n\t\treturn\n\t}\n\n\tnode := treenode.GetNodeInTree(tree, id)\n\tif nil == node {\n\t\terr = fmt.Errorf(Conf.Language(15), id)\n\t\treturn\n\t}\n\n\tif ast.NodeHeading != node.Type {\n\t\treturn\n\t}\n\n\tvar nodes []*ast.Node\n\tnodes = append(nodes, node)\n\tnodes = append(nodes, treenode.HeadingChildren(node)...)\n\thiddenNodes := map[string]bool{}\n\tfor _, hidden := range treenode.CollectFoldHiddenNodes(node.Parent) {\n\t\thiddenNodes[hidden.ID] = true\n\t}\n\n\ttransaction = &Transaction{}\n\tluteEngine := util.NewLute()\n\tfor _, n := range nodes {","sourceCodeStart":825,"sourceCodeEnd":861,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/model/block.go#L825-L861","documentation":"Conf.Language(15) renders as 'Content block with id [%s] not found'. GetHeadingDeleteTransaction loads the document tree via LoadTreeByBlockID(id) — which succeeded — but treenode.GetNodeInTree(tree, id) then fails to find the node with that ID inside the loaded tree. This means the blocktree index still maps the ID to a document, but the document content no longer contains it: a stale index or the block was deleted/renumbered since indexing. Returned by POST /api/block/getHeadingDeleteTransaction with code=-1 and closeTimeout=7000.","triggerScenarios":"POST /api/block/getHeadingDeleteTransaction with a heading ID that was deleted in the meantime (edited in another window/device, synced change, or refactored by a plugin) while the blocktree index was not yet updated; also an ID that only exists in a different document than the tree it resolved to.","commonSituations":"Stale block IDs cached by frontend code or plugins; concurrent edits via sync or multiple windows; index not rebuilt after data rollback or manual workspace surgery; passing a document ID where a heading ID is required in rare resolution edge cases.","solutions":["Re-fetch the current block ID (e.g. via /api/query/SQL or /api/block/getBlockInfo) and retry with a fresh ID","If IDs are persistently missing, rebuild the index (Settings - Search - Rebuild index, or the doc tree rebuild option)","Flush pending transactions before relying on IDs right after heavy edits","Handle the error gracefully in the UI (this is what closeTimeout=7000 in the response hints at)"],"exampleFix":"// before\nconst tx = await fetchSyncPost(\"/api/block/getHeadingDeleteTransaction\", {id: cachedHeadingID})\n\n// after: refresh the ID before requesting the delete transaction\nconst rows = await fetchSyncPost(\"/api/query/sql\", {stmt: `select id from blocks where id = '${cachedHeadingID}'`})\nif (rows.data.length === 0) {\n    // block gone: drop the stale reference\n    return\n}\nconst tx = await fetchSyncPost(\"/api/block/getHeadingDeleteTransaction\", {id: cachedHeadingID})","handlingStrategy":"validation","validationCode":"// Verify the block still exists before building a heading-delete transaction\nrows := sqlQuery(fmt.Sprintf(\"select id from blocks where id = '%s'\", id))\nif len(rows) == 0 { return fmt.Errorf(\"block %s no longer exists\", id) }\ntransaction, err := model.GetHeadingDeleteTransaction(id)","typeGuard":"func blockExists(id string) bool {\n    rows, err := model.QuerySQL(fmt.Sprintf(\"select id from blocks where id = '%s'\", id))\n    return nil == err && 0 < len(rows)\n}","tryCatchPattern":"transaction, err := model.GetHeadingDeleteTransaction(id)\nif err != nil {\n    if strings.Contains(err.Error(), \"not found\") {\n        // stale ID: drop cached references and refresh the doc; do not blindly retry the same ID\n        return refreshAndRetryOnce(id)\n    }\n    return err\n}","preventionTips":["Never cache heading IDs across editing sessions; re-query at action time","After sync or heavy edits, rebuild the index before operating on captured IDs","Treat 'not found' from heading transaction APIs as a signal to refresh, not as a hard failure"],"tags":["siyuan","block","heading","index","stale-id"],"backgroundTag":"block-id-not-found","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}