siyuan-note/siyuan · error
parse tree [ ] failed
Error message
parse tree [%s] failed
What it means
After reading the file, `importFromLocalPath` parses it with `parseStdMd` (Lute). If the parser returns a nil tree, the kernel logs and returns `parse tree [<localPath>] failed` to the caller. This means the file content could not be built into a valid Markdown AST — typically an unreadable/empty file or content Lute rejected at the parse stage.
Solutions
- Verify the file is real UTF-8 Markdown text (`file`, `head`, or opening it in an editor); re-export if it is binary or wrong encoding
- Check the kernel log for the logged `parse tree [...] failed` line to confirm which path failed, then inspect that exact file
- Convert the file to UTF-8 and remove corrupted content, then retry the import
Example fix
// before
// importing a UTF-16 encoded file exported by another tool
importFromLocalPath("/notes/doc.md", toPath) // parse tree [/notes/doc.md] failed
// after
// re-save the file as UTF-8 plain Markdown, then import
importFromLocalPath("/notes/doc-utf8.md", toPath) Defensive patterns
Strategy: validation
Validate before calling
const buf = await fs.readFile(localPath);
const text = buf.toString("utf8");
if (text.length === 0 || /\u0000/.test(text.slice(0, 512))) {
throw new Error("File is empty or binary; not importable Markdown");
} Type guard
function looksLikeTextMarkdown(buf: Buffer): boolean {
return buf.length > 0 && !buf.subarray(0, 512).includes(0);
} Try / catch
try {
await api.importFromLocalPath(localPath, toPath);
} catch (e) {
if (String(e.message).startsWith("parse tree")) {
// re-encode file to UTF-8 and retry, or skip and report to user
}
} Prevention
- Ensure exports are UTF-8 plain-text Markdown before import
- Never rename binary files to .md; verify content with a text editor
- Check kernel logs for the 'parse tree [...] failed' entry to identify the bad file
When it happens
Trigger: Calling the import API with an `.md`/`.markdown` file whose bytes produce a nil tree from `parseStdMd` — e.g. empty file, binary content with an `.md` extension, or an encoding Lute cannot handle.
Common situations: Renamed binary files (PDF/zip renamed to `.md`); zero-byte exports from other tools; files in non-UTF-8 encodings (GBK, UTF-16) whose bytes break parsing; corrupted downloads.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- 347
- Conf.Language(79)
- empty result
- HTML to Markdown conversion failed
- import from local path failed, please check kernel log for…
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/051f0f2a58376e73.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/import.go:1805
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 9f775e8a12)