siyuan-note/siyuan · error
found invalid ID [ ]
Error message
found invalid ID [%s]
What it means
DataBlockDOM converts markdown block-update data into SiYuan block DOM. While walking the produced tree it validates every node ID; any node carrying an ID that is not a well-formed block ID sets invalidID, and the function returns this error instead of producing DOM. It guards against markdown pasted with foreign or corrupted {{select}} / {: id="..."} attributes.
Solutions
- Strip or regenerate ID attributes in the markdown before sending (send plain markdown without {: id=...})
- Only reuse IDs that were obtained from SiYuan itself (SQL blocks table / getBlockKramdown)
- Use dataType="dom" with valid, round-tripped block DOM instead of hand-crafted markdown
- Sanitize imported markdown with a regex removing invalid IAL id attributes prior to the call
Example fix
// before
const md = 'Paragraph text {: id="bad-id!!"}';
await updateBlock(id, 'markdown', md);
// after
const md = 'Paragraph text'; // let SiYuan generate a fresh valid ID
await updateBlock(id, 'markdown', md); Defensive patterns
Strategy: validation
Validate before calling
function hasValidBlockIDs(markdown) {
const ials = markdown.matchAll(/\{:\s*id="([^"]+)"/g);
for (const m of ials) {
if (!/^[0-9]{14}-[0-9a-z]{7}$/.test(m[1])) return false;
}
return true;
} Try / catch
try {
await updateBlock(id, 'markdown', md);
} catch (e) {
if (String(e.msg || e).includes('invalid ID')) {
const cleaned = md.replace(/\s*\{:\s*id="[^"]*"\}/g, '');
await updateBlock(id, 'markdown', cleaned);
} else { throw e; }
} Prevention
- Never hand-write {: id=...} IAL attributes; let SiYuan generate them
- Strip foreign id-like attributes when importing markdown from other tools
- Only reuse IDs read from SiYuan's own exports
When it happens
Trigger: Calling parseBlockUpdateData with dataType="markdown" where the markdown text embeds custom node-ID attributes that fail ID validation — e.g. manually authored {: id="123"} attributes, IDs copied from another workspace with different node-id format, or truncated/corrupted IDs.
Common situations: Pasting markdown exported from other tools (Notion, Obsidian) that carries id-like attributes; hand-edited .sy content or programmatically generated markdown with fake IDs; migration of content between SiYuan instances with modified ID schemes.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/befc4e4b5f8c4024.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/block_update.go:198
blankParagraph := treenode.NewParagraph("")
ret = luteEngine.RenderNodeBlockDOM(blankParagraph)
}
invalidID := ""
if nil != tree && nil != tree.Root {
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering {
return ast.WalkContinue
}
if "" != n.ID && !ast.IsNodeIDPattern(n.ID) {
invalidID = n.ID
return ast.WalkStop
}
return ast.WalkContinue
})
}
if "" != invalidID {
return "", errors.New("found invalid ID [" + invalidID + "]")
}
return
}
func parseBlockUpdateData(data, dataType string, luteEngine *lute.Lute) (ret string, tree *parse.Tree, err error) {
ret = data
switch dataType {
case "markdown":
ret, err = DataBlockDOM(data, luteEngine)
if err != nil {
err = fmt.Errorf("data block DOM failed: %w", err)
return
}
case "dom":
default:
err = fmt.Errorf("unsupported block data type [%s]", dataType)
return
}View on GitHub (pinned to 8641553a1f)