{"record":{"id":"394ab542e84ecfb2","repo":"siyuan-note/siyuan","slug":"asset-path-does-not-belong-to-a-notebook-s","errorCode":null,"errorMessage":"asset path does not belong to a notebook: %s","messagePattern":"asset path does not belong to a notebook: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":928,"sourceCode":"\t\treturn\n\t}\n\n\tparts := strings.Split(filepath.ToSlash(dataRelativePath), \"/\")\n\tassetDirIndex := -1\n\tswitch {\n\tcase len(parts) > 1 && parts[0] == \"assets\":\n\t\tassetDirIndex = 0\n\tcase len(parts) > 2 && ast.IsNodeIDPattern(parts[0]):\n\t\tfor i := 1; i < len(parts)-1; i++ {\n\t\t\tif parts[i] == \"assets\" {\n\t\t\t\tassetDirIndex = i\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif assetDirIndex > 0 {\n\t\t\tboxConfPath := filepath.Join(util.DataDir, parts[0], \".siyuan\", \"conf.json\")\n\t\t\tif !filelock.IsExist(boxConfPath) {\n\t\t\t\terr = fmt.Errorf(\"asset path does not belong to a notebook: %s\", assetPath)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif IsEncryptedBox(parts[0]) {\n\t\t\t\terr = fmt.Errorf(\"accessing assets in encrypted notebook [%s] is not supported\", parts[0])\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\tif assetDirIndex < 0 {\n\t\terr = fmt.Errorf(\"path is not under an assets directory: %s\", assetPath)\n\t\treturn\n\t}\n\n\tassetRootParts := parts[:assetDirIndex+1]\n\tassetRoot := filepath.Join(util.DataDir, filepath.FromSlash(strings.Join(assetRootParts, \"/\")))\n\tif !gulu.File.IsSubPath(assetRoot, absPath) {\n\t\terr = fmt.Errorf(\"path is not a child of assets directory: %s\", assetPath)\n\t\treturn","sourceCodeStart":910,"sourceCodeEnd":946,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/assets.go#L910-L946","documentation":"Returned by ResolveDataAssetPath when the first path segment matches ast.IsNodeIDPattern (looks like a notebook ID) and an assets/ segment exists under it, but <data>/<id>/.siyuan/conf.json does not exist on disk — meaning that notebook ID is not actually a registered notebook. The offending path is interpolated.","triggerScenarios":"Passing a path like \"20200101000000-abcdef/assets/x.png\" where the notebook 20200101000000-abcdef does not exist in this workspace; a notebook was deleted but its assets remain; a workspace switch left stale references.","commonSituations":"Cross-workspace path leakage; a stale bookmark/reference to a deleted notebook; a typo or truncated notebook ID.","solutions":["Verify the notebook ID exists (check the notebooks API / conf.json on disk) before resolving.","If the notebook was deleted, remove the dangling reference and re-resolve against a valid notebook.","Switch to the workspace that actually contains that notebook."],"exampleFix":"// before\nrel, abs, err := model.ResolveDataAssetPath(\"20200101000000-xx/assets/a.png\")\n\n// after — confirm the notebook exists first\nboxConfPath := filepath.Join(util.DataDir, \"20200101000000-xx\", \".siyuan\", \"conf.json\")\nif !filelock.IsExist(boxConfPath {\n    return errors.New(\"notebook not mounted in this workspace\")\n}\nrel, abs, err := model.ResolveDataAssetPath(\"20200101000000-xx/assets/a.png\")","handlingStrategy":"validation","validationCode":"parts := strings.Split(filepath.ToSlash(filepath.Clean(assetPath)), \"/\")\nif len(parts) > 2 && ast.IsNodeIDPattern(parts[0]) {\n    boxConf := filepath.Join(util.DataDir, parts[0], \".siyuan\", \"conf.json\")\n    if !filelock.IsExist(boxConf) {\n        return fmt.Errorf(\"notebook %s not present in workspace\", parts[0])\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Confirm the notebook is mounted before resolving paths into it.","Switch to the correct workspace if referencing a notebook from another workspace.","Drop stale references to deleted notebooks."],"tags":["validation","assets","notebook"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}