{"record":{"id":"dc9b0e048aba4a8d","repo":"siyuan-note/siyuan","slug":"list-document-images-failed-w","errorCode":null,"errorMessage":"list document images failed: %w","messagePattern":"list document images failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":364,"sourceCode":"\treturn errors.As(err, &target)\n}\n\nfunc markImageExecutionUnknown(err error) error {\n\tif err == nil || IsImageExecutionUnknown(err) {\n\t\treturn err\n\t}\n\treturn &imageExecutionUnknownError{err: err}\n}\n\n// ListDocumentImages 返回文档引用的本地图片，供智能体工具和编辑器功能复用。\nfunc ListDocumentImages(documentID string) (DocumentImageList, error) {\n\tbt, err := resolveMultimodalDocument(documentID)\n\tif err != nil {\n\t\treturn DocumentImageList{}, err\n\t}\n\tpaths, err := DocImageAssets(bt.RootID)\n\tif err != nil {\n\t\treturn DocumentImageList{}, fmt.Errorf(\"list document images failed: %w\", err)\n\t}\n\trefs := make([]ImageArtifactRef, 0, len(paths))\n\tseen := map[string]bool{}\n\tfor _, assetPath := range paths {\n\t\tif !strings.HasPrefix(AssetPathWithoutQuery(assetPath), \"assets/\") || seen[assetPath] {\n\t\t\tcontinue\n\t\t}\n\t\tseen[assetPath] = true\n\t\trefs = append(refs, ImageArtifactRef{Kind: \"image\", Path: assetPath, DocumentID: bt.RootID})\n\t}\n\treturn DocumentImageList{DocumentID: bt.RootID, Images: refs}, nil\n}\n\n// 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\")","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/assets.go#L346-L382","documentation":"Returned by ListDocumentImages when DocImageAssets(rootID) fails. DocImageAssets loads the document's .sy tree via LoadTreeByBlockID and walks the AST collecting NodeImage link destinations; the %w wraps the underlying tree-load or walk error. This is an infrastructure/data error, not a validation error.","triggerScenarios":"Calling ListDocumentImages with a documentID that resolves to a block tree whose .sy file is missing, corrupt, unreadable on disk, or fails to parse via LoadTreeByBlockID. The documentID itself passed resolveMultimodalDocument (so it exists in blocktree.db), but the on-disk tree load failed.","commonSituations":"The blocktree index is stale (block deleted but blocktree.db not yet updated), the .sy file was removed manually or by sync conflict, the file is locked by another process, or the data directory was moved while the kernel was running.","solutions":["Run a kernel data-index rebuild / notebook reindex so blocktree.db matches on-disk .sy files.","Verify the .sy file exists on disk under <data>/<boxID>/<path> for the resolved rootID.","Check the kernel log (the wrapped error names the exact tree-load failure) and address that root cause.","If the document was legitimately deleted, treat the error as a not-found and stop listing it."],"exampleFix":"// before\nlist, err := model.ListDocumentImages(docID)\nif err != nil { return err }\n\n// after — distinguish index/IO failure from empty result\nlist, err := model.ListDocumentImages(docID)\nif err != nil {\n    logging.LogErrorf(\"list images for %s: %s\", docID, err)\n    return err // surface to caller; do not retry in a tight loop\n}\n_ = list","handlingStrategy":"try-catch","validationCode":"// Validate the document still exists in the blocktree index first.\nbt := treenode.GetBlockTree(strings.TrimSpace(documentID))\nif bt == nil {\n    return errors.New(\"document not found\")\n}\n// Then call; DocImageAssets may still fail on disk parse — handle as try-catch.","typeGuard":null,"tryCatchPattern":"list, err := model.ListDocumentImages(documentID)\nif err != nil {\n    // wrapped error — log the root cause, do not auto-retry in a loop\n    logging.LogErrorf(\"list document images %s: %s\", documentID, err)\n    return err\n}","preventionTips":["Keep blocktree.db consistent with on-disk .sy files by reindexing after manual file operations.","Do not hold or reuse document IDs across kernel restarts without re-validating via GetBlockTree.","Surface the wrapped error rather than swallowing it — the underlying cause is the actionable detail."],"tags":["assets","documents","io","tree-load"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}