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

  1. Strip or regenerate ID attributes in the markdown before sending (send plain markdown without {: id=...})
  2. Only reuse IDs that were obtained from SiYuan itself (SQL blocks table / getBlockKramdown)
  3. Use dataType="dom" with valid, round-tripped block DOM instead of hand-crafted markdown
  4. 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

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)