siyuan-note/siyuan · error

parse tree failed

Error message

parse tree failed

What it means

Returned by parseBlockUpdateData after BlockDOM2Tree(ret). If the parsed tree is nil, its Root is nil, or firstContentBlock(tree.Root) is nil, the input DOM has no usable content block. The DOM parsed to completion but produced an empty or root-only tree.

Source

Thrown at kernel/model/block_update.go:220

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
	}

	tree = luteEngine.BlockDOM2Tree(ret)
	if nil == tree || nil == tree.Root || nil == firstContentBlock(tree.Root) {
		err = errors.New("parse tree failed")
	}
	return
}

func normalizeBlockUpdateTree(oldNode *ast.Node, tree *parse.Tree, luteEngine *lute.Lute) (ret *parse.Tree, updatedNode *ast.Node, err error) {
	updatedNode, err = resolveBlockUpdateNode(oldNode, tree.Root)
	if err != nil {
		return nil, nil, err
	}

	updatedNode.Unlink()
	root := &ast.Node{Type: ast.NodeDocument}
	root.AppendChild(updatedNode)
	ret = &parse.Tree{
		Root:    root,
		Context: &parse.Context{ParseOption: luteEngine.ParseOptions},
	}
	return

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Inspect the DOM string - confirm it contains at least one addressable content block.
  2. Strip zero-width characters and pure-whitespace nodes before submission.
  3. Regenerate the DOM from a known-good source (re-render the block in the editor and copy its DOM).
Defensive patterns

Strategy: validation

Validate before calling

// trim zero-width / whitespace-only content before submission
cleaned := strings.ReplaceAll(input.Data, "\u200b", "")
if strings.TrimSpace(stripTags(cleaned)) == "" {
    return errors.New("empty content")
}

Try / catch

ops, roots, err := buildBlockUpdateOperations(inputs, resolver, loader)
if err != nil && strings.Contains(err.Error(), "parse tree failed") {
    // regenerate DOM in the editor and retry
}

Prevention

When it happens

Trigger: DOM with only whitespace/zero-width characters; DOM consisting solely of container elements with no leaf content; DOM whose first content block was stripped by Lute sanitization.

Common situations: Pasting an empty paragraph; DOM that is all list containers with no list items; sanitization stripping all content leaving an empty shell.

Related errors


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