siyuan-note/siyuan · error
HTML to Markdown conversion failed
Error message
HTML to Markdown conversion failed: %s
What it means
When format is 'markdown' (the default), WebFetch converts the fetched HTML with lute's HTML2Markdown via the panic-protected safeHTML2Markdown wrapper; a non-nil conversion error is wrapped as 'HTML to Markdown conversion failed: <cause>'. This indicates the Lute engine rejected or failed on the specific HTML content, not a network problem.
Solutions
- Retry with format="text" which uses safeHTML2Text and never returns a conversion error
- Inspect the wrapped cause after 'HTML to Markdown conversion failed: ' for the specific Lute failure
- Sanitize or simplify the HTML upstream if you control the source page
- Check the Lute version if the same URL previously converted fine — behavior may have changed upstream
Example fix
// before
md, err := WebFetch(url, "markdown") // conversion fails on malformed HTML
// after
text, err := WebFetch(url, "text") // fall back to plain-text extraction
if err == nil {
md = text
} Defensive patterns
Strategy: fallback
Try / catch
md, err := WebFetch(url, "markdown")
if err != nil && strings.Contains(err.Error(), "conversion failed") {
md, err = WebFetch(url, "text") // text path has no conversion error return
} Prevention
- Prefer pages with reasonably well-formed HTML for Markdown conversion
- Fall back to format="text" when conversion fails
- Pin and test the Lute version when upgrading — conversion behavior changes
- Log the failing URL so pathological sources can be sanitized or blacklisted
When it happens
Trigger: engine.HTML2Markdown returns an error for pathological or malformed HTML (deeply nested structures, encoding oddities, input the converter cannot process).
Common situations: Fetching pages with heavily malformed tag soup; documents with exotic encodings that survived the fetch as invalid UTF-8; upstream Lute version changes altering conversion behavior on edge-case markup.
Related errors
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/7b577c767d450162.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/webfetch.go:109
isHTML := strings.HasPrefix(contentType, "text/html")
if !isHTML {
return truncateRunes(htmlStr, maxWebFetchChars), nil
}
if htmlStr == "" {
return "", nil
}
engine := NewLute()
var result string
switch format {
case "text":
result, _ = safeHTML2Text(engine, htmlStr)
default: // markdown
md, mdErr := safeHTML2Markdown(engine, htmlStr)
if mdErr != nil {
return "", errors.New("HTML to Markdown conversion failed: " + mdErr.Error())
}
result = md
}
if result == "" {
return htmlStr, nil
}
return truncateRunes(result, maxWebFetchChars), nil
}
func safeHTML2Markdown(engine *lute.Lute, htmlStr string) (result string, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("HTML to Markdown panicked: %v", r)
}
}()
result, err = engine.HTML2Markdown(htmlStr)View on GitHub (pinned to 9f775e8a12)