{"record":{"id":"051f0f2a58376e73","repo":"siyuan-note/siyuan","slug":"parse-tree-s-failed","errorCode":null,"errorMessage":"parse tree [%s] failed","messagePattern":"parse tree \\[(.+?)\\] failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/import.go","lineNumber":1504,"sourceCode":"\t\tif !strings.HasSuffix(fileName, \".md\") && !strings.HasSuffix(fileName, \".markdown\") {\n\t\t\treturn errors.New(Conf.Language(79))\n\t\t}\n\n\t\ttitle := strings.TrimSuffix(fileName, \".markdown\")\n\t\ttitle = strings.TrimSuffix(title, \".md\")\n\t\ttargetPath := strings.TrimSuffix(toPath, \".sy\")\n\t\tid := ast.NewNodeID()\n\t\ttargetPath = path.Join(targetPath, id+\".sy\")\n\t\tvar data []byte\n\t\tdata, err = os.ReadFile(localPath)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttree, yfmRootID, yfmTitle, yfmUpdated := parseStdMd(data)\n\t\tif nil == tree {\n\t\t\tmsg := fmt.Sprintf(\"parse tree [%s] failed\", localPath)\n\t\t\tlogging.LogError(msg)\n\t\t\treturn errors.New(msg)\n\t\t}\n\n\t\tif \"\" != yfmRootID {\n\t\t\tid = yfmRootID\n\t\t}\n\t\tif \"\" != yfmTitle {\n\t\t\ttitle = yfmTitle\n\t\t}\n\t\tunescapedTitle, unescapeErr := url.PathUnescape(title)\n\t\tif nil == unescapeErr {\n\t\t\ttitle = unescapedTitle\n\t\t}\n\t\tupdated := yfmUpdated\n\t\tfname := path.Base(targetPath)\n\t\ttargetPath = strings.ReplaceAll(targetPath, fname, id+\".sy\")\n\n\t\ttree.ID = id\n\t\ttree.Root.ID = id","sourceCodeStart":1486,"sourceCodeEnd":1522,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/import.go#L1486-L1522","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: a zero-byte or binary file named notes.md is imported, producing nil tree\ndata, err := os.ReadFile(localPath)\n// ...\ntree, yfmRootID, yfmTitle, yfmUpdated := parseStdMd(data)\nif nil == tree {\n    msg := fmt.Sprintf(\"parse tree [%s] failed\", localPath)\n    logging.LogError(msg)\n    return errors.New(msg)\n}\n\n// after: validate the file is non-empty text before attempting parse\nif len(bytes.TrimSpace(data)) == 0 {\n    return fmt.Errorf(\"file [%s] is empty, nothing to import\", localPath)\n}\ntree, yfmRootID, yfmTitle, yfmUpdated := parseStdMd(data)","handlingStrategy":"validation","validationCode":"// Validate the file is non-empty, valid UTF-8 text before calling the import path\nfunc validateMarkdownImport(localPath string) error {\n    info, err := os.Stat(localPath)\n    if err != nil { return fmt.Errorf(\"stat: %w\", err) }\n    if info.Size() == 0 { return errors.New(\"file is empty\") }\n    data, err := os.ReadFile(localPath)\n    if err != nil { return err }\n    if !utf8.Valid(data) { return errors.New(\"file is not valid UTF-8\") }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Wrap the import call and surface a user-friendly message on parse failure\nresult, err := importData(localPath)\nif err != nil && strings.Contains(err.Error(), \"parse tree [\") {\n    return fmt.Errorf(\"the file could not be parsed as Markdown; check it is valid UTF-8 text: %w\", err)\n}","preventionTips":["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."],"tags":["import","markdown","lute-parser","parsing"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}