siyuan-note/siyuan · error
read image failed: %w
Error message
read image failed: %w
What it means
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.
Source
Thrown at kernel/model/assets.go:396
// PrepareDocumentImage 校验并读取文档实际引用的本地资源图片,供当前模型直接接收图片输入。
func PrepareDocumentImage(documentID, assetPath string) (PreparedDocumentImage, error) {
assetPath = strings.TrimSpace(assetPath)
if assetPath == "" {
return PreparedDocumentImage{}, errors.New("assetPath is required for analyze")
}
if !strings.HasPrefix(AssetPathWithoutQuery(assetPath), "assets/") {
return PreparedDocumentImage{}, errors.New("only local assets/... images are supported")
}
bt, err := resolveMultimodalDocument(documentID)
if err != nil {
return PreparedDocumentImage{}, err
}
if !documentReferencesImage(bt.RootID, assetPath) {
return PreparedDocumentImage{}, errors.New("assetPath is not an image referenced by the document")
}
data, err := ReadAssetBytesInBox(bt.BoxID, assetPath)
if err != nil {
return PreparedDocumentImage{}, fmt.Errorf("read image failed: %w", err)
}
prepared, err := util.PrepareModelImage(
data, documentImageMaxBytes, documentImageMaxPixels, documentImageMaxEdge,
)
if err != nil {
return PreparedDocumentImage{}, err
}
return PreparedDocumentImage{
Artifact: ImageArtifactRef{Kind: "image", Path: assetPath, DocumentID: bt.RootID},
Data: prepared.Data,
MIMEType: prepared.MIMEType,
Prepared: prepared,
}, nil
}
// GenerateImage 使用全局图片生成配置创建图片字节,可供文档资源、编辑器和其他图片入口复用。
func GenerateImage(ctx context.Context, request GenerateImageRequest) (GenerateImageResult, error) {
if Conf == nil || Conf.AI == nil {View on GitHub (pinned to 251596fc0d)
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.
Example fix
// before
prepared, err := model.PrepareDocumentImage(docID, p)
if err != nil { return err }
// after — classify the wrapped read error
prepared, err := model.PrepareDocumentImage(docID, p)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
// asset missing on disk — refresh doc references
return fmt.Errorf("asset vanished, re-add it: %w", err)
}
return err
} Defensive patterns
Strategy: try-catch
Try / catch
prepared, err := model.PrepareDocumentImage(documentID, assetPath)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
// asset gone from disk — refresh references, do not retry unchanged
return fmt.Errorf("asset missing on disk: %w", err)
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- enable encrypted notebook failed: failed to persist key back
- refuse to write decrypted asset inside workspace
- source is not an encrypted asset
- invalid .sy base name [%s]: must end with .sy
- write data [%s] failed: %s
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/a2b8e119b66764a0.
Report an issue: GitHub.