{"record":{"id":"0f589837dd0d3d37","repo":"siyuan-note/siyuan","slug":"save-generated-image-failed-w","errorCode":null,"errorMessage":"save generated image failed: %w","messagePattern":"save generated image failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":461,"sourceCode":"\t\tData: generated.Data, MIMEType: generated.MIMEType, Extension: generated.Extension, RevisedPrompt: generated.RevisedPrompt,\n\t}, nil\n}\n\n// GenerateDocumentImage 使用通用图片生成能力创建文档资源。\nfunc GenerateDocumentImage(ctx context.Context, request GenerateDocumentImageRequest) (GenerateDocumentImageResult, error) {\n\tbt, err := resolveMultimodalDocument(request.DocumentID)\n\tif err != nil {\n\t\treturn GenerateDocumentImageResult{}, err\n\t}\n\tgenerated, err := GenerateImage(ctx, GenerateImageRequest{\n\t\tPrompt: request.Prompt, Size: request.Size, Quality: request.Quality, OutputFormat: request.OutputFormat,\n\t})\n\tif err != nil {\n\t\treturn GenerateDocumentImageResult{}, err\n\t}\n\tassetPath, _, err := InsertAssetBytes(bt.RootID, \"ai-image\"+generated.Extension, generated.Data)\n\tif err != nil {\n\t\treturn GenerateDocumentImageResult{}, markImageExecutionUnknown(fmt.Errorf(\"save generated image failed: %w\", err))\n\t}\n\treturn GenerateDocumentImageResult{\n\t\tArtifact: ImageArtifactRef{\n\t\t\tKind: \"image\", Path: assetPath, MIMEType: generated.MIMEType, DocumentID: bt.RootID,\n\t\t},\n\t\tRevisedPrompt: generated.RevisedPrompt,\n\t}, nil\n}\n\nfunc resolveMultimodalDocument(documentID string) (*treenode.BlockTree, error) {\n\tbt := treenode.GetBlockTree(strings.TrimSpace(documentID))\n\tif bt == nil {\n\t\treturn nil, errors.New(\"document not found: \" + documentID)\n\t}\n\treturn bt, nil\n}\n\nfunc validateImageModel(provider *conf.Provider, imageModel *conf.Model) error {","sourceCodeStart":443,"sourceCodeEnd":479,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/assets.go#L443-L479","documentation":"Returned by GenerateDocumentImage when InsertAssetBytes(bt.RootID, ...) fails after a successful image generation. InsertAssetBytes looks up the block tree, computes the assets dir, mkdir's it, hashes/dedups, and writes the file. The error is wrapped with markImageExecutionUnknown because the image has already been generated (and may be billed) — the bytes exist in memory but could not be persisted.","triggerScenarios":"The block tree entry for the document disappeared between the resolveMultimodalDocument call and the InsertAssetBytes call; the assets directory cannot be created (read-only data dir, disk full); os.MkdirAll or writeAssetFile fails due to permissions or path length; the asset data is empty (shouldn't happen post-generation but is guarded).","commonSituations":"Disk full on the volume holding util.DataDir; data dir on a read-only mount; antivirus blocks the write on Windows; the doc was deleted in a concurrent operation.","solutions":["Free disk space and ensure util.DataDir is writable.","Check the wrapped error: a 'block not found' (Conf.Language(71)) means the doc vanished mid-call — refresh the block tree and re-resolve.","Do not retry blindly: the provider call already succeeded (IsImageExecutionUnknown is true); persist manually if you still have the bytes."],"exampleFix":"// before\nres, err := model.GenerateDocumentImage(ctx, req)\nif err != nil { return err } // loses the generated bytes\n\n// after — surface the unknown-execution nature to the user\nres, err := model.GenerateDocumentImage(ctx, req)\nif err != nil {\n    if model.IsImageExecutionUnknown(err) {\n        // image was generated but not saved; tell the user, offer re-save\n        return fmt.Errorf(\"image generated but save failed (you may be charged): %w\", err)\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"func isImageExecUnknown(err error) bool { return model.IsImageExecutionUnknown(err) }","tryCatchPattern":"res, err := model.GenerateDocumentImage(ctx, req)\nif err != nil {\n    if model.IsImageExecutionUnknown(err) {\n        // image was generated (possibly billed) but not saved — do not retry blindly\n        return fmt.Errorf(\"generation ok but save failed: %w\", err)\n    }\n    return err\n}","preventionTips":["Keep free disk space on the util.DataDir volume.","Ensure the data directory is writable and not on a read-only mount.","If save fails, tell the user the generation may have been billed — do not silently retry."],"tags":["io","ai","filesystem","no-retry","persistence"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}