{"record":{"id":"8c51a3f737a8ffb5","repo":"siyuan-note/siyuan","slug":"query-asset-failed-s","errorCode":null,"errorMessage":"Query asset failed [%s]","messagePattern":"Query asset failed \\[(.+?)\\]","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":1119,"sourceCode":"\t\t\tif !gulu.File.IsSubPath(util.WorkspaceDir, realP) {\n\t\t\t\treturn \"\", fmt.Errorf(\"symlink [%s] resolves outside workspace: [%s]\", p, realP)\n\t\t\t}\n\t\t\t// 验证解析后的路径仍在 <boxID>/assets/ 或全局 data/assets/ 下\n\t\t\texpectedPrefix := filepath.Join(util.DataDir, \"assets\")\n\t\t\tif boxID != \"\" {\n\t\t\t\texpectedPrefix = filepath.Join(util.DataDir, boxID, \"assets\")\n\t\t\t}\n\t\t\tif !gulu.File.IsSubPath(expectedPrefix, realP) {\n\t\t\t\treturn \"\", fmt.Errorf(\"symlink [%s] resolves outside assets directory: [%s]\", p, realP)\n\t\t\t}\n\t\t}\n\t\treturn p, nil\n\t}\n\t// 非加密 box 的资源可能回退到全局 data/assets（兼容旧笔记本结构）\n\tif !IsEncryptedBox(boxID) {\n\t\treturn GetAssetAbsPathWithOpt(relativePath, false)\n\t}\n\treturn \"\", fmt.Errorf(Conf.Language(12), relativePath)\n}\n\n// GetAssetAbsPathWithOpt 与 GetAssetAbsPath 一致，但可通过 includeEncrypted 控制是否遍历加密 box。\n// serveAssets 传 true（下游 serveEncryptedAsset 会按锁定状态 fail-closed），其他调用方传 false（安全跳过）。\nfunc GetAssetAbsPathWithOpt(relativePath string, includeEncrypted bool) (string, error) {\n\trelativePath = strings.TrimSpace(relativePath)\n\tif idx := strings.Index(relativePath, \"?\"); idx >= 0 {\n\t\trelativePath = relativePath[:idx]\n\t}\n\n\tabsPath, err := getAssetAbsPath(relativePath, includeEncrypted)\n\tif err == nil && absPath != \"\" {\n\t\treturn absPath, nil\n\t}\n\n\tif err != nil {\n\t\treturn \"\", err\n\t}","sourceCodeStart":1101,"sourceCodeEnd":1137,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/assets.go#L1101-L1137","documentation":"Thrown by GetAssetAbsPathInBox (kernel/model/assets.go:1119) in the encrypted-box branch. When boxID is an encrypted notebook and the asset is not found under `<boxID>/assets/`, the resolver does NOT fall back to global `data/assets/` (encrypted boxes are resource islands), so it returns this localized not-found error. Conf.Language(12) renders as `Query asset failed [%s]`.","triggerScenarios":"Calling GetAssetAbsPathInBox(path, boxID) where boxID is an encrypted notebook and the referenced asset does not exist under that box's own assets directory. The asset may exist globally or in another notebook, but encrypted-box isolation forbids the fallback.","commonSituations":"An asset reference inside an encrypted notebook points to a global/notebook-shared asset that was never copied into the encrypted box; the encrypted box's assets directory is incomplete after a partial sync; a document was moved into an encrypted notebook without migrating its assets.","solutions":["Confirm the asset actually exists under `<DataDir>/<boxID>/assets/`.","If the asset lives in global `data/assets/` or another notebook, copy it into the encrypted box's assets directory (encrypted boxes cannot read external assets).","If the box is not meant to be encrypted, verify IsEncryptedBox(boxID) returns what you expect (check the box's encryption/lock state).","Re-run the encrypted-box sync/decryption so the local assets directory is complete, then retry."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before resolving in an encrypted box, confirm the asset exists there.\nif model.IsEncryptedBox(boxID) {\n    p := filepath.Join(util.DataDir, boxID, filepath.FromSlash(rel))\n    if !gulu.File.IsExist(p) {\n        return fmt.Errorf(\"asset %s not present in encrypted box %s; copy it in first\", rel, boxID)\n    }\n}","typeGuard":null,"tryCatchPattern":"if _, err := model.GetAssetAbsPathInBox(ref, box); err != nil {\n    if model.IsEncryptedBox(box) && strings.Contains(err.Error(), \"Query asset failed\") {\n        // encrypted-box isolation: no global fallback; copy the asset into the box, then retry\n    }\n}","preventionTips":["Copy referenced assets into an encrypted notebook before/when moving documents into it.","Remember encrypted boxes are resource islands — they cannot read global/other-box assets.","Ensure encrypted-box sync/decryption is complete before resolving assets."],"tags":["assets","encrypted-box","not-found","notebooks","security"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}