{"record":{"id":"4614246bf4066f01","repo":"siyuan-note/siyuan","slug":"document-not-found-documentid","errorCode":null,"errorMessage":"document not found: <documentID>","messagePattern":"document not found: <documentID>","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/assets.go","lineNumber":474,"sourceCode":"\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 {\n\tif provider == nil || imageModel == nil {\n\t\treturn errors.New(\"image model is not configured\")\n\t}\n\tif provider.Protocol != \"\" && provider.Protocol != \"openai\" {\n\t\treturn fmt.Errorf(\"unsupported multimodal provider protocol: %s\", provider.Protocol)\n\t}\n\treturn nil\n}\n\nfunc documentReferencesImage(rootID, assetPath string) bool {\n\tpaths, err := DocImageAssets(rootID)\n\tif err != nil {\n\t\treturn false","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/assets.go#L456-L492","documentation":"Returned by resolveMultimodalDocument when treenode.GetBlockTree(strings.TrimSpace(documentID)) returns nil — the ID is not present in the in-memory blocktree.db index. This helper backs ListDocumentImages, PrepareDocumentImage, and GenerateDocumentImage, so all three surface it. The literal documentID (pre-trim) is interpolated into the message.","triggerScenarios":"Passing a non-existent, malformed, or whitespace-padded document ID; an ID that was deleted; an ID from a different workspace whose blocktree hasn't been loaded; calling before the kernel indexed the notebooks.","commonSituations":"Stale client-side cached doc ID after the doc was deleted; copy/paste truncated the ID; the kernel just started and hasn't finished initial indexing; wrong workspace is mounted.","solutions":["Validate documentID format (it must match ast.IsNodeIDPattern — a 14-20 digit timestamp) before calling.","Ensure the kernel has finished booting and indexing notebooks before issuing the call.","If the ID is stale, re-query the doc list / search to get a fresh ID."],"exampleFix":"// before\nimgs, err := model.ListDocumentImages(docID) // docID may be stale/garbage\n\n// after — validate the ID shape first\nif !ast.IsNodeIDPattern(strings.TrimSpace(docID)) {\n    return errors.New(\"invalid document ID\")\n}\nimgs, err := model.ListDocumentImages(docID)","handlingStrategy":"validation","validationCode":"docID := strings.TrimSpace(documentID)\nif !ast.IsNodeIDPattern(docID) {\n    return errors.New(\"invalid document ID format\")\n}\nif treenode.GetBlockTree(docID) == nil {\n    return errors.New(\"document not found\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate the document ID shape (NodeIDPattern) at the request boundary.","Wait for kernel indexing to complete before issuing doc-based calls.","Re-query for fresh IDs when a doc may have been deleted."],"tags":["validation","documents","blocktree"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}