siyuan-note/siyuan · warning

found invalid ID [%s]

Error message

found invalid ID [%s]

What it means

Returned by the post-normalization validation pass in the block-update pipeline. After building the new subtree, ast.Walk scans every node; any node whose ID is non-empty but fails ast.IsNodeIDPattern sets invalidID and the function returns 'found invalid ID [<id>]'. This catches malformed IDs in user-supplied input data (markdown/dom) before they are committed.

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 251596fc0d)

Solutions

  1. Strip or regenerate block IDs in the input before submitting (let Lute mint fresh IDs).
  2. Validate every {...} IAL ID in the markdown against ast.IsNodeIDPattern before the update.
  3. When using dom input, ensure all id= attributes match the SiYuan block ID pattern.

Example fix

// before
// markdown contains: text{ id="abc def" }

// after
// regenerate the id with a SiYuan-format id, e.g.
// text{ id="20240101000000abcdef" }
Defensive patterns

Strategy: validation

Validate before calling

// scan the input DOM/markdown for IAL ids and validate each
re := regexp.MustCompile(`\{[^}]*id="([^"]+)"`)
for _, m := range re.FindAllStringSubmatch(input.Data, -1) {
    if !ast.IsNodeIDPattern(m[1]) {
        return fmt.Errorf("invalid id in input: %q", m[1])
    }
}

Prevention

When it happens

Trigger: User-supplied markdown contains a kramdown block IAL with a hand-written malformed ID; DOM input embeds a non-SiYuan ID; an integration synthesizes IDs with the wrong format.

Common situations: Hand-authored markdown with {...} attributes using arbitrary strings; pasted content from another system that preserves foreign IDs; Lute producing an unexpected ID shape from exotic syntax.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/befc4e4b5f8c4024. Report an issue: GitHub.