{"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":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":396,"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// GenerateImage 使用全局图片生成配置创建图片字节，可供文档资源、编辑器和其他图片入口复用。\nfunc GenerateImage(ctx context.Context, request GenerateImageRequest) (GenerateImageResult, error) {\n\tif Conf == nil || Conf.AI == nil {","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/assets.go#L378-L414","documentation":"Returned by PrepareDocumentImage when ReadAssetBytesInBox(bt.BoxID, assetPath) fails. ReadAssetBytesInBox resolves the asset to an absolute path inside the box and os.ReadFile's it (decrypting for encrypted notebooks). The %w wraps the underlying OS read, path-resolution, or decryption error.","triggerScenarios":"The asset was deleted from disk but is still referenced by the AST (index/disk drift); the file is locked or unreadable due to permissions; an encrypted-notebook asset is requested but the box read lock / DEK cannot be acquired; the path resolves outside the box assets directory.","commonSituations":"Sync removed or renamed the asset; an antivirus/backup process holds an exclusive lock on Windows; the user logged out of an encrypted notebook so GetDEKIfUnlocked fails; the data dir is on a disconnected external drive.","solutions":["Inspect the wrapped error: os.PathError means missing/locked file, a decryption error means the box is locked — unlock it first.","If the asset is gone, re-insert it into the document and update the reference before retrying.","For encrypted notebooks, ensure the user has unlocked the notebook in this kernel session before calling."],"exampleFix":"// before\nprepared, err := model.PrepareDocumentImage(docID, p)\nif err != nil { return err }\n\n// after — classify the wrapped read error\nprepared, err := model.PrepareDocumentImage(docID, p)\nif err != nil {\n    if errors.Is(err, os.ErrNotExist) {\n        // asset missing on disk — refresh doc references\n        return fmt.Errorf(\"asset vanished, re-add it: %w\", err)\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"prepared, err := model.PrepareDocumentImage(documentID, assetPath)\nif err != nil {\n    if errors.Is(err, fs.ErrNotExist) {\n        // asset gone from disk — refresh references, do not retry unchanged\n        return fmt.Errorf(\"asset missing on disk: %w\", err)\n    }\n    return err\n}","preventionTips":["For encrypted notebooks, ensure the box is unlocked in the session before reading.","Avoid concurrent processes that delete assets out from under the editor.","Inspect the wrapped error — it tells you whether it is missing-file, lock, or decryption."],"tags":["io","assets","encryption","filesystem"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}