{"record":{"id":"de907c0d8146b5dc","repo":"siyuan-note/siyuan","slug":"resolve-assets-root-s-failed-w","errorCode":null,"errorMessage":"resolve assets root [%s] failed: %w","messagePattern":"resolve assets root \\[(.+?)\\] failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":1300,"sourceCode":"\t\treturn \"\", err\n\t}\n\treturn \"\", fmt.Errorf(Conf.Language(12), relativePath)\n}\n\nfunc getAssetAbsPath(relativePath string, includeEncrypted bool) (absPath string, err error) {\n\trelativePath = filepath.ToSlash(relativePath)\n\t// 在 data 文件夹下搜索，主要是 data/assets 文件夹\n\tp := filepath.Join(util.DataDir, relativePath)\n\tif gulu.File.IsExist(p) {\n\t\tif !gulu.File.IsSubPath(util.WorkspaceDir, p) {\n\t\t\treturn \"\", fmt.Errorf(\"[%s] is not sub path of workspace\", p)\n\t\t}\n\t\t// 解析符号链接，验证真实路径仍在 data/assets/ 下\n\t\tif realP, evalErr := filepath.EvalSymlinks(p); evalErr == nil && realP != p {\n\t\t\tassetsRoot := util.GetDataAssetsAbsPath()\n\t\t\trealAssetsRoot, rootEvalErr := filepath.EvalSymlinks(assetsRoot)\n\t\t\tif rootEvalErr != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"resolve assets root [%s] failed: %w\", assetsRoot, rootEvalErr)\n\t\t\t}\n\t\t\tif !gulu.File.IsSubPath(realAssetsRoot, realP) {\n\t\t\t\treturn \"\", fmt.Errorf(\"symlink [%s] resolves outside data/assets: [%s]\", p, realP)\n\t\t\t}\n\t\t\t// 安全校验使用解析后的路径，返回原路径以便下游与 DataDir 保持同一路径形式\n\t\t\treturn p, nil\n\t\t}\n\t\treturn p, nil\n\t}\n\n\t// 在文档同级 assets 文件夹下搜索\n\tif !strings.HasPrefix(relativePath, \"assets/\") {\n\t\treturn \"\", nil\n\t}\n\tnotebooks, err := ListNotebooks()\n\tif err != nil {\n\t\treturn \"\", errors.New(Conf.Language(0))\n\t}","sourceCodeStart":1282,"sourceCodeEnd":1318,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/assets.go#L1282-L1318","documentation":"When the found asset path is a symlink, getAssetAbsPath resolves both the symlink target and the data/assets root with filepath.EvalSymlinks. This error is returned if EvalSymlinks fails on the assets root itself (util.GetDataAssetsAbsPath()), wrapped as \"resolve assets root [%s] failed: %w\". It indicates the workspace's data/assets directory cannot be canonically resolved on disk.","triggerScenarios":"getAssetAbsPath hits the symlink branch (EvalSymlinks(p) succeeds and differs from p) but filepath.EvalSymlinks(assetsRoot) returns an error — e.g. the data/assets directory does not exist, was deleted, or a permission/IO error prevents resolution.","commonSituations":"Workspaces where data/assets was removed or renamed while a doc still references a symlinked asset; symlink setups on network mounts or Windows junctions where EvalSymlinks fails; partial workspace restores missing the assets folder.","solutions":["Ensure <workspace>/data/assets exists and is accessible; create it if missing","Check filesystem permissions on data/assets so the process can stat and resolve it","Recreate the data/assets directory (EvalSymlinks fails on non-existent paths) and re-import the asset","If data/assets is itself a symlink, verify the target exists and is reachable by the kernel process"],"exampleFix":"// before\nassetsRoot := util.GetDataAssetsAbsPath()\n// after\nassetsRoot := util.GetDataAssetsAbsPath()\nif _, err := os.Stat(assetsRoot); os.IsNotExist(err) {\n    os.MkdirAll(assetsRoot, 0755) // EvalSymlinks fails when the root is missing\n}","handlingStrategy":"fallback","validationCode":"if _, err := os.Stat(util.GetDataAssetsAbsPath()); err != nil {\n    os.MkdirAll(util.GetDataAssetsAbsPath(), 0755)\n}","typeGuard":null,"tryCatchPattern":"abs, err := model.GetAssetAbsPath(rel)\nif err != nil && strings.HasPrefix(err.Error(), \"resolve assets root\") {\n    log.Printf(\"data/assets broken, check workspace layout: %v\", err)\n}","preventionTips":["Keep data/assets present and writable in every workspace","Verify symlink targets survive workspace moves and restores","Test workspaces on network mounts for EvalSymlinks behavior"],"tags":["go","filesystem","symlink","assets"],"backgroundTag":"file-not-found","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"}