{"record":{"id":"c9e692fff7c7a441","repo":"siyuan-note/siyuan","slug":"invalid-path","errorCode":null,"errorMessage":"invalid path","messagePattern":"invalid path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/filesys/tree.go","lineNumber":255,"sourceCode":"\ttreenode.UpgradeSpec(tree)\n\tescapeAttributeValues(tree)\n\treturn\n}\n\nfunc LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err error) {\n\tret, err = parseJSON2Tree(boxID, p, data, luteEngine)\n\tif nil != err {\n\t\tlogging.LogErrorf(\"parse tree [%s] failed: %s\", p, err)\n\t\treturn\n\t}\n\tret.Path = p\n\tret.Root.Path = p\n\n\thPath := \"/\" + strings.TrimPrefix(filepath.ToSlash(p), \"/\")\n\tparts := strings.Split(hPath, \"/\")\n\tif len(parts) < 2 {\n\t\tlogging.LogErrorf(\"parse tree [%s] failed: invalid path\", p)\n\t\terr = errors.New(\"invalid path\")\n\t\treturn\n\t}\n\n\tparts = parts[1 : len(parts)-1] // 去掉开头的斜杆和结尾的自己\n\tif 1 > len(parts) {\n\t\tret.HPath = \"/\" + ret.Root.IALAttr(\"title\")\n\t\tret.Hash = treenode.NodeHash(ret.Root, ret, luteEngine)\n\t\treturn\n\t}\n\n\t// 构造 HPath\n\thPathBuilder := bytes.Buffer{}\n\thPathBuilder.WriteString(\"/\")\n\tfor i := range parts {\n\t\tvar parentAbsPath string\n\t\tif 0 < i {\n\t\t\tparentAbsPath = strings.Join(parts[:i+1], \"/\")\n\t\t} else {","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/filesys/tree.go#L237-L273","documentation":"LoadTreeByData builds a tree from raw data and derives the hPath from the given relative path p. It splits the slash-normalized path and requires at least two segments (leading empty segment plus the document name). Fewer segments means the path is malformed (e.g. empty, \"doc.sy\" without a leading slash, or just \"/\"), so it fails with \"invalid path\".","triggerScenarios":"Calling LoadTreeByData with p == \"\", a bare file name like \"doc.sy\", or \"/\" — any path where strings.Split of \"/\"+trimmed p yields fewer than 2 parts.","commonSituations":"Passing a path missing its leading slash; a variable that was supposed to hold the document path left empty; callers constructing paths without the notebook-relative \"/folder/doc.sy\" form.","solutions":["Pass a proper notebook-relative path with a leading slash, e.g. \"/doc.sy\" or \"/folder/doc.sy\".","Check the variable supplying p is populated before the call.","Normalize the path with filepath.ToSlash and ensure it is not empty."],"exampleFix":"// before\nLoadTreeByData(boxID, \"doc.sy\", data, lute)\n// after\nLoadTreeByData(boxID, \"/doc.sy\", data, lute)","handlingStrategy":"validation","validationCode":"function isValidDocPath(p) {\n  const norm = \"/\" + String(p || \"\").replace(/^\\/+/, \"\");\n  return norm.split(\"/\").length >= 2 && norm.length > 1;\n}","typeGuard":null,"tryCatchPattern":"if err := filesys.LoadTreeByData(boxID, p, data, lute); err != nil {\n    // invalid or unparseable path; fix the path argument\n}","preventionTips":["Ensure document paths are notebook-relative with a leading slash.","Never pass empty or bare file-name paths.","Normalize separators to \"/\" before calling."],"tags":["validation","path","document-tree"],"backgroundTag":"invalid-argument-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}