{"record":{"id":"12b3de77773b2c67","repo":"siyuan-note/siyuan","slug":"resolve-assets-directory-s-failed-w","errorCode":null,"errorMessage":"resolve assets directory [%s] failed: %w","messagePattern":"resolve assets directory \\[(.+?)\\] failed: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":951,"sourceCode":"\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\n\t}\n\n\tresolvedRoot, evalErr := filepath.EvalSymlinks(assetRoot)\n\tif evalErr != nil {\n\t\terr = fmt.Errorf(\"resolve assets directory [%s] failed: %w\", assetRoot, evalErr)\n\t\treturn\n\t}\n\tif assetDirIndex > 0 {\n\t\tnotebookRoot := filepath.Join(util.DataDir, parts[0])\n\t\tresolvedDataDir, dataEvalErr := filepath.EvalSymlinks(util.DataDir)\n\t\tresolvedNotebookRoot, notebookEvalErr := filepath.EvalSymlinks(notebookRoot)\n\t\tif dataEvalErr != nil || notebookEvalErr != nil ||\n\t\t\t!gulu.File.IsSubPath(resolvedDataDir, resolvedNotebookRoot) ||\n\t\t\t!gulu.File.IsSubPath(resolvedNotebookRoot, resolvedRoot) {\n\t\t\terr = fmt.Errorf(\"notebook asset path resolves outside notebook directory: %s\", assetPath)\n\t\t\treturn\n\t\t}\n\t}\n\tresolvedPath, evalErr := filepath.EvalSymlinks(absPath)\n\tif evalErr != nil {\n\t\terr = fmt.Errorf(\"resolve asset [%s] failed: %w\", absPath, evalErr)\n\t\treturn\n\t}","sourceCodeStart":933,"sourceCodeEnd":969,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/assets.go#L933-L969","documentation":"Thrown by ResolveDataAssetPath (kernel/model/assets.go:951) when filepath.EvalSymlinks fails on the reconstructed assets root directory (either global `data/assets/` or a notebook's `<boxID>/assets/`). EvalSymlinks fails when the directory does not exist, when any link in the chain is broken, or when the process lacks permission to traverse a component.","triggerScenarios":"Calling ResolveDataAssetPath with a path whose `assets` directory component does not exist on disk (e.g. the notebook's assets folder was deleted or never created), or where the assets directory is a dangling symlink, or where a parent directory has restrictive permissions (0o000 / owned by another user).","commonSituations":"Workspace was copied/moved between machines and symlinks broke; a notebook directory was partially deleted leaving a conf.json but no assets/ dir; running the kernel under a different OS user than the one that owns DataDir; backup restore that recreated files but not directory symlinks.","solutions":["Check whether the assets root printed in [%s] actually exists on disk: `ls -la` on that path and each parent.","If it is a broken symlink, remove it and let SiYuan recreate the directory (or restore from backup).","Fix ownership/permissions so the kernel process can traverse every component (chmod +x on parent dirs, chown to the running user).","If the assets directory legitimately should not exist for this notebook, do not call ResolveDataAssetPath for it; gate the call on existence first."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Ensure the assets root exists and is resolvable before resolving.\nassetRoot := filepath.Join(util.DataDir, \"assets\") // or <box>/assets\nif _, err := filepath.EvalSymlinks(assetRoot); err != nil {\n    return fmt.Errorf(\"assets root unavailable, refusing to resolve: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if _, _, err := model.ResolveDataAssetPath(p); err != nil {\n    if strings.Contains(err.Error(), \"resolve assets directory\") {\n        // surface a user-facing 'assets folder missing' message rather than a raw stack\n    }\n    return err\n}","preventionTips":["Keep the workspace on a local, non-removable filesystem to avoid missing assets roots.","After moving the workspace, run a consistency check so broken symlinks/missing dirs are recreated.","Run the kernel under a user that owns or can traverse the entire DataDir path."],"tags":["assets","symlinks","filesystem","permissions","workspace"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}