{"record":{"id":"a2b8e119b66764a0","repo":"siyuan-note/siyuan","slug":"read-image-failed-w","errorCode":null,"errorMessage":"read image failed: %w","messagePattern":"read image failed: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":469,"sourceCode":"// PrepareDocumentImage 校验并读取文档实际引用的本地资源图片，供当前模型直接接收图片输入。\nfunc PrepareDocumentImage(documentID, assetPath string) (PreparedDocumentImage, error) {\n\tassetPath = strings.TrimSpace(assetPath)\n\tif assetPath == \"\" {\n\t\treturn PreparedDocumentImage{}, errors.New(\"assetPath is required for analyze\")\n\t}\n\tif !strings.HasPrefix(AssetPathWithoutQuery(assetPath), \"assets/\") {\n\t\treturn PreparedDocumentImage{}, errors.New(\"only local assets/... images are supported\")\n\t}\n\tbt, err := resolveMultimodalDocument(documentID)\n\tif err != nil {\n\t\treturn PreparedDocumentImage{}, err\n\t}\n\tif !documentReferencesImage(bt.RootID, assetPath) {\n\t\treturn PreparedDocumentImage{}, errors.New(\"assetPath is not an image referenced by the document\")\n\t}\n\tdata, err := ReadAssetBytesInBox(bt.BoxID, assetPath)\n\tif err != nil {\n\t\treturn PreparedDocumentImage{}, fmt.Errorf(\"read image failed: %w\", err)\n\t}\n\tprepared, err := util.PrepareModelImage(\n\t\tdata, documentImageMaxBytes, documentImageMaxPixels, documentImageMaxEdge,\n\t)\n\tif err != nil {\n\t\treturn PreparedDocumentImage{}, err\n\t}\n\treturn PreparedDocumentImage{\n\t\tArtifact: ImageArtifactRef{Kind: \"image\", Path: assetPath, DocumentID: bt.RootID},\n\t\tData:     prepared.Data,\n\t\tMIMEType: prepared.MIMEType,\n\t\tPrepared: prepared,\n\t}, nil\n}\n\n// PrepareAgentMessageImage 校验并读取智能体用户消息引用的全局资源图片。\nfunc PrepareAgentMessageImage(assetPath string) (PreparedDocumentImage, error) {\n\tassetPath = strings.TrimSpace(assetPath)","sourceCodeStart":451,"sourceCodeEnd":487,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/assets.go#L451-L487","documentation":"After the reference check succeeds, the image bytes are read from the document's notebook box via ReadAssetBytesInBox; any read failure is wrapped as \"read image failed\". The file may be missing, unreadable, or fail validation in the box-aware reader.","triggerScenarios":"Calling PrepareDocumentImage when the referenced asset file was deleted from the box's assets directory, the box path resolution fails, or OS-level read errors occur (permissions, broken symlink).","commonSituations":"Asset file removed by manual cleanup or a failed sync while the document reference remains; wrong box (notebook) moved or renamed; permission problems on the data directory.","solutions":["Inspect the wrapped %w cause in kernel logs to distinguish not-found vs permission errors","Restore the missing asset file or re-insert the image into the document","Check filesystem permissions and the box (notebook) directory location, then retry"],"exampleFix":"// caller-side guard\nif _, err := os.Stat(filepath.Join(boxDir, assetPath)); err != nil { /* re-import image first */ }\nprepared, err := PrepareDocumentImage(docID, assetPath)","handlingStrategy":"try-catch","validationCode":"if _, err := os.Stat(filepath.Join(dataDir, assetPath)); err != nil { /* asset file missing from box */ }","typeGuard":null,"tryCatchPattern":"prepared, err := PrepareDocumentImage(docID, assetPath)\nif err != nil { var wrapped interface{ Unwrap() error }; if errors.As(err, &wrapped) { log.Errorf(\"read image: %v\", errors.Unwrap(err)) }; return retryAfterReimport(docID, assetPath) }","preventionTips":["Do not manually delete files under data/assets while references exist","Re-sync or re-import after sync conflicts to restore missing asset files","Verify data directory permissions for the kernel process user"],"tags":["go","file-read","assets","filesystem"],"backgroundTag":"file-read-failed","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"}