siyuan-note/siyuan · error
parse tree [%s] failed
Error message
parse tree [%s] failed
What it means
Thrown when importing a single Markdown file (the non-directory branch of the import flow) and the Lute parser fails to produce an AST. parseStdMd calls parse.Parse() from the 88250/lute engine; if that returns a nil tree the file is considered unparseable as standard Markdown. The error message embeds the local file path so the offending file is identifiable. This is a hard stop — no document is created for the file.
Source
Thrown at kernel/model/import.go:1504
if !strings.HasSuffix(fileName, ".md") && !strings.HasSuffix(fileName, ".markdown") {
return errors.New(Conf.Language(79))
}
title := strings.TrimSuffix(fileName, ".markdown")
title = strings.TrimSuffix(title, ".md")
targetPath := strings.TrimSuffix(toPath, ".sy")
id := ast.NewNodeID()
targetPath = path.Join(targetPath, id+".sy")
var data []byte
data, err = os.ReadFile(localPath)
if err != nil {
return err
}
tree, yfmRootID, yfmTitle, yfmUpdated := parseStdMd(data)
if nil == tree {
msg := fmt.Sprintf("parse tree [%s] failed", localPath)
logging.LogError(msg)
return errors.New(msg)
}
if "" != yfmRootID {
id = yfmRootID
}
if "" != yfmTitle {
title = yfmTitle
}
unescapedTitle, unescapeErr := url.PathUnescape(title)
if nil == unescapeErr {
title = unescapedTitle
}
updated := yfmUpdated
fname := path.Base(targetPath)
targetPath = strings.ReplaceAll(targetPath, fname, id+".sy")
tree.ID = id
tree.Root.ID = idView on GitHub (pinned to 251596fc0d)
Solutions
- Open the file named in the error message in a text editor and confirm it is valid UTF-8 Markdown; fix or remove corrupt content.
- Check the file is not zero-length or binary: run `file <localPath>` and verify it reports ASCII/UTF-8 text.
- If the file contains YAML front matter, validate its syntax (correct `---` delimiters, no tabs where spaces are required).
- As a workaround, re-save the file as clean Markdown or convert it through an external tool (e.g. pandoc) before importing.
Example fix
// before: a zero-byte or binary file named notes.md is imported, producing nil tree
data, err := os.ReadFile(localPath)
// ...
tree, yfmRootID, yfmTitle, yfmUpdated := parseStdMd(data)
if nil == tree {
msg := fmt.Sprintf("parse tree [%s] failed", localPath)
logging.LogError(msg)
return errors.New(msg)
}
// after: validate the file is non-empty text before attempting parse
if len(bytes.TrimSpace(data)) == 0 {
return fmt.Errorf("file [%s] is empty, nothing to import", localPath)
}
tree, yfmRootID, yfmTitle, yfmUpdated := parseStdMd(data) Defensive patterns
Strategy: validation
Validate before calling
// Validate the file is non-empty, valid UTF-8 text before calling the import path
func validateMarkdownImport(localPath string) error {
info, err := os.Stat(localPath)
if err != nil { return fmt.Errorf("stat: %w", err) }
if info.Size() == 0 { return errors.New("file is empty") }
data, err := os.ReadFile(localPath)
if err != nil { return err }
if !utf8.Valid(data) { return errors.New("file is not valid UTF-8") }
return nil
} Try / catch
// Wrap the import call and surface a user-friendly message on parse failure
result, err := importData(localPath)
if err != nil && strings.Contains(err.Error(), "parse tree [") {
return fmt.Errorf("the file could not be parsed as Markdown; check it is valid UTF-8 text: %w", err)
} Prevention
- Sanitize imported files to valid UTF-8 before offering them to the import flow.
- Reject zero-byte and binary files in the UI file picker before submitting.
- Validate YAML front matter delimiters if present in imported Markdown.
When it happens
Trigger: Importing a single .md/.markdown file whose content Lute cannot parse into a tree (e.g. a file containing only invalid bytes, a null-laden or binary file with a .md extension, or content that triggers a parser-level nil return). Triggered via the import-data API path that handles individual file imports, not the directory-walk branch.
Common situations: A .md file that is actually binary or zero-byte; a file with encoding issues or embedded NUL bytes; a corrupted download renamed to .md; an empty file that the Lute engine declines to wrap in a tree; a file with malformed YAML front matter that confuses the YFM-enabled parser.
Related errors
- import from local path failed, please check kernel log for d
- Only supports importing Markdown document
- Obsidian Vault has no readable Markdown
- invalid import token
- import task not found or expired
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/051f0f2a58376e73.
Report an issue: GitHub.