siyuan-note/siyuan · error
Content block with id
Error message
Content block with id [%s] not found
What it means
kernel/model/blockial.go:100, from SetBlockReminder (language key 15): the block's document loaded successfully via LoadTreeByBlockID, but treenode.GetNodeInTree found no node with that ID inside it. The reminder operation aborts before any attribute is written. Practically: the ID is stale (block deleted/merged since you learned it) or the block index mapped the ID to a document that no longer contains it.
Solutions
- Re-resolve the ID immediately before the call: /api/query select id from blocks where id='...'.
- If it should exist, rebuild the index (Settings - Search - rebuild index) to fix stale blocktree.db mappings.
- Check File - History / recycle bin if the deletion was accidental.
Defensive patterns
Strategy: validation
Validate before calling
// Verify the block still exists before updating
const q = await fetch("/api/query", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ stmt: `select id, type, root_id from blocks where id='${blockID}'` }),
});
const qr = await q.json();
if (!qr.data?.length) throw new Error(`Block ${blockID} no longer exists`); Type guard
async function reminderTargetExists(id: string): Promise<boolean> {
const r = await fetch("/api/query", { method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ stmt: `select id from blocks where id='${id}'` }) });
const j = await r.json();
return j.code === 0 && (j.data?.length ?? 0) > 0;
} Try / catch
try {
await setBlockReminder(id, timed);
} catch (e) {
if (/Content block with id \[.*\] not found/.test(e.message)) {
const fresh = await resolveBlockByText(anchorText); // re-discover target
if (fresh) await setBlockReminder(fresh, timed);
} else throw e;
} Prevention
- Resolve reminder targets in the same transaction window as the write.
- Filter stored ID lists against the blocks table before batch scheduling.
When it happens
Trigger: POST /api/attr/setBlockReminder with an ID from an old query/cached list after the block was deleted or its document restructured; racing with sync deletions; well-formed ID belonging to a block in another document due to index staleness.
Common situations: Reminder scripts iterating saved block IDs; schedules computed offline then applied after the user edited/deleted blocks; multi-client sync removing blocks between query and write.
Related errors
- Conf.Language(15)
- 0
- AI editor action not found
- duplicate document ID
- Encrypted notebooks do not support this operation
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/f43c88662159b5d4.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/blockial.go:100
if "0" != timed {
t, e := dateparse.ParseIn(timed, time.Now().Location())
if nil != e {
return e
}
timedMills = t.UnixMilli()
}
FlushTxQueue()
attrs := sql.GetBlockAttrs(id)
tree, err := LoadTreeByBlockID(id)
if err != nil {
return
}
node := treenode.GetNodeInTree(tree, id)
if nil == node {
return fmt.Errorf(Conf.Language(15), id)
}
if ast.NodeDocument != node.Type && node.IsContainerBlock() {
node = treenode.FirstLeafBlock(node)
}
content := sql.NodeStaticContent(node, nil, false, false, false)
content = gulu.Str.SubStr(content, 128)
content = strings.ReplaceAll(content, editor.Zwsp, "")
err = SetCloudBlockReminder(id, content, timedMills)
if err != nil {
return
}
attrName := "custom-reminder-wechat"
if "0" == timed {
delete(attrs, attrName)
old := node.IALAttr(attrName)View on GitHub (pinned to afa823b6b4)