siyuan-note/siyuan · error
empty IFrame block
Error message
empty IFrame block
What it means
htmlAssetIFrameBlockDOM converts a generated iframe markdown snippet into a block DOM tree via Lute and expects the tree to contain a root with a first child block. If Lute produced an empty tree (nil root or no first child), parsing failed silently and this error reports it instead of returning a bogus block ID.
Source
Thrown at kernel/mcp/tools/asset.go:189
name = "component.html"
}
name = filepath.Base(name)
ext := strings.ToLower(filepath.Ext(name))
if ext != ".html" && ext != ".htm" {
return "", fmt.Errorf("name must end in .html or .htm")
}
return name, nil
}
func htmlAssetIFrameBlockDOM(assetPath string) (dom, blockID string, err error) {
src := html.EscapeString(model.HTMLAssetIFrameSrc(assetPath))
dom, err = markdownToBlockDOM(`<iframe sandbox="allow-scripts" src="` + src + `" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>`)
if err != nil {
return
}
tree := util.NewLute().BlockDOM2Tree(dom)
if tree == nil || tree.Root == nil || tree.Root.FirstChild == nil {
return "", "", fmt.Errorf("empty IFrame block")
}
blockID = tree.Root.FirstChild.ID
return
}
func newAssetUploadToolResult(succeeded []model.AssetUploadSuccess, failed []model.AssetUploadFailure) CallToolResult {
var sb strings.Builder
sb.WriteString(fmt.Sprintf("Uploaded %d file(s):\n", len(succeeded)))
for _, result := range succeeded {
sb.WriteString(fmt.Sprintf("- %s -> %s\n", result.Name, result.Path))
}
if 0 < len(failed) {
sb.WriteString(fmt.Sprintf("\nFailed %d file(s):\n", len(failed)))
for _, result := range failed {
sb.WriteString(fmt.Sprintf("- %s: %s\n", result.Name, result.Error))
}
}
return CallToolResult{Content: []ContentItem{{Type: "text", Text: sb.String()}}, IsError: 0 < len(failed)}View on GitHub (pinned to 8641553a1f)
Solutions
- Check whether markdownToBlockDOM returned an empty string or error and propagate it before calling BlockDOM2Tree
- Verify the Lute version parses raw HTML iframe blocks (test with util.NewLute().BlockDOM2Tree on a minimal iframe snippet)
- If a sanitizer/filter strips iframe, adjust the parsing options so the iframe markdown is preserved
Example fix
// before
dom, err = markdownToBlockDOM(iframeMD)
if err != nil { return } // dom may be empty, error surfaces later
// after
dom, err = markdownToBlockDOM(iframeMD)
if err != nil { return }
if dom == "" { return "", "", fmt.Errorf("empty DOM for iframe block") } Defensive patterns
Strategy: validation
Validate before calling
tree := util.NewLute().BlockDOM2Tree(dom)
if tree == nil || tree.Root == nil || tree.Root.FirstChild == nil { return errors.New("parsed DOM is empty") } Type guard
func hasFirstChildBlock(tree *parse.Tree) bool { return tree != nil && tree.Root != nil && tree.Root.FirstChild != nil } Try / catch
blockID, dom, err := htmlAssetIFrameBlockDOM(assetPath)
if err != nil && strings.Contains(err.Error(), "empty IFrame block") {
// re-render the DOM or upgrade/inspect the Lute parsing path
} Prevention
- Check markdownToBlockDOM output for empty strings before tree conversion
- Keep Lute updated and add a regression test parsing an iframe snippet
- Avoid sanitizer settings that strip raw HTML iframe tags
When it happens
Trigger: markdownToBlockDOM rendered the iframe snippet into an empty/invalid DOM — e.g. Lute configuration stripped the raw HTML iframe, markdownToBlockDOM returned "", or BlockDOM2Tree failed to parse the produced DOM string.
Common situations: A Lute version change altering raw-HTML/iframe parsing; markdownToBlockDOM returning empty output due to an upstream error that wasn't propagated; unusual sanitizer settings filtering iframe tags.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- parse OAuth challenge: %w
- parse tree [%s] failed
- Invalid attribute view rich text style entity
- tool arguments are not valid JSON: %w
- attribute view content is unavailable
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/edaa956d9e614d17.
Report an issue: GitHub.