siyuan-note/siyuan · error
empty result
Error message
empty result
What it means
markdownToBlockDOM (kernel/mcp/tools/block.go) converts markdown via Lute's Md2BlockDOMTree; if Lute yields an empty string the tool cannot build a block and returns this error. It guards block insert/append/prepend and HTML-asset iframe creation from writing empty content.
Solutions
- Provide non-empty markdown content in the tool call
- Trim-check content client-side before invoking and skip the call if blank
- If content is raw HTML, wrap it in a fenced HTML or kramdown block so Lute produces a DOM
- Check the returned error path: if Lute silently fails, log the input markdown to find the culprit
Example fix
// before
await call("insert_block", {content: ""})
// after
if (!md.trim()) throw new Error("refusing to insert empty markdown")
await call("insert_block", {content: md}) Defensive patterns
Strategy: validation
Validate before calling
if (typeof md !== "string" || !md.trim()) throw new Error("markdown content required"); Type guard
const isNonEmptyString = (s) => typeof s === "string" && s.trim().length > 0;
Try / catch
try { await call("block_insert", {content: md}) } catch (e) { if (String(e).includes("empty result")) { console.error("markdown produced no DOM:", md); } } Prevention
- Never pass empty or whitespace-only markdown
- Wrap raw HTML in fenced blocks
- Log the markdown input when this error occurs
When it happens
Trigger: Passing an empty markdown string, or content that Lute reduces to nothing (e.g. only whitespace/HTML tags with SetHTMLTag2TextMark yielding no DOM) to blockInsert, blockAppend, blockPrepend, htmlAssetIFrameBlockDOM or dailynoteAppend.
Common situations: An MCP client sends an empty or whitespace-only content field; a script pipes an empty template file; HTML-only content stripped to nothing by the tag-to-textmark conversion.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- 347
- HTML to Markdown conversion failed
- parse template tree failed
- parse tree [ ] failed
- parse tree [ ] failed
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/c665d11095eac5ab.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/mcp/tools/block.go:430
}
return CallToolResult{Content: []ContentItem{{Type: "text", Text: "block deleted: " + id}}}, nil
}
func getBlockData(args map[string]any) (data, dataType string) {
data, _ = args["data"].(string)
dataType, _ = args["dataType"].(string)
if dataType == "" {
dataType = "markdown"
}
return
}
func markdownToBlockDOM(md string) (string, error) {
luteEngine := util.NewLute()
luteEngine.SetHTMLTag2TextMark(true)
result, _ := luteEngine.Md2BlockDOMTree(md, true)
if result == "" {
return "", fmt.Errorf("empty result")
}
return result, nil
}
func blockMove(args map[string]any) (CallToolResult, error) {
id, _ := args["id"].(string)
if id == "" {
return CallToolResult{Content: []ContentItem{{Type: "text", Text: "id is required"}}, IsError: true}, nil
}
parentID, _ := args["parentID"].(string)
if parentID == "" {
return CallToolResult{Content: []ContentItem{{Type: "text", Text: "parentID is required"}}, IsError: true}, nil
}
previousID, _ := args["previousID"].(string)
boxID, release, scopeErr := beginBlockToolScope(args, true, id, parentID, previousID)
if scopeErr != nil {
return blockToolError(scopeErr.Error())
}View on GitHub (pinned to 9f775e8a12)