{"record":{"id":"10a3c4f9b1bb72f1","repo":"Tencent/WeKnora","slug":"attachment-not-found","errorCode":null,"errorMessage":"attachment not found","messagePattern":"attachment not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/temporary_document.go","lineNumber":254,"sourceCode":"\t\t\tif strings.TrimPrefix(strings.ToLower(strings.TrimSpace(fileType)), \".\") == wanted {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\nfunc (s *temporaryDocumentService) Get(ctx context.Context, tenantID uint64, sessionID, documentID string) (*types.TemporaryDocument, error) {\n\treturn s.repo.GetScoped(ctx, tenantID, sessionID, documentID)\n}\n\nfunc (s *temporaryDocumentService) OpenFile(ctx context.Context, tenantID uint64, sessionID, documentID string) (io.ReadCloser, string, error) {\n\tdocument, err := s.repo.GetScoped(ctx, tenantID, sessionID, documentID)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\tif document == nil {\n\t\treturn nil, \"\", fmt.Errorf(\"attachment not found\")\n\t}\n\tfile, err := s.fileService.GetFile(ctx, document.ResourceRef)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\treturn file, document.FileName, nil\n}\n\nfunc (s *temporaryDocumentService) List(ctx context.Context, tenantID uint64, sessionID string) ([]*types.TemporaryDocument, error) {\n\treturn s.repo.ListScoped(ctx, tenantID, sessionID)\n}\n\nfunc (s *temporaryDocumentService) Delete(ctx context.Context, tenantID uint64, sessionID, documentID string) error {\n\tdocument, err := s.repo.GetScoped(ctx, tenantID, sessionID, documentID)\n\tif err != nil || document == nil {\n\t\treturn err\n\t}\n\tfor _, ref := range temporaryDocumentImageRefs(document.ImageRefs) {","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/temporary_document.go#L236-L272","documentation":"OpenFile looks up the document scoped to tenant+session+documentID; a nil result with no error means no matching attachment exists in that scope, and the service returns this error. It is a scoping-aware not-found: the document may exist but under a different tenant or session.","triggerScenarios":"Opening a documentID that was already expired/purged; wrong sessionID paired with a valid documentID; cross-tenant access attempts where the ID exists in another tenant.","commonSituations":"Clients caching document IDs past session expiry; copy-pasting IDs between sessions; multi-tenant routing bugs sending the wrong tenantID.","solutions":["Verify tenantID, sessionID and documentID all match the values used at Create time","Check whether the document expired or was cleaned up; re-upload if needed","Treat as user-facing not-found and offer re-upload rather than retrying","Add logging of the lookup tuple to catch tenant/session mismatches"],"exampleFix":"// before\ndoc, err := repo.GetScoped(ctx, tenantID, sessionID, documentID)\nif doc == nil { panic(\"missing\") }\n// after\ndoc, err := repo.GetScoped(ctx, tenantID, sessionID, documentID)\nif doc == nil {\n    return ErrAttachmentNotFound // maps to 404 for the client\n}","handlingStrategy":"fallback","validationCode":"// Caller-side: confirm the document was created and not expired in this session first.\nif doc.ExpiresAt.Before(time.Now()) { return ErrAttachmentExpired }","typeGuard":"func documentVisible(d *types.TemporaryDocument) bool { return d != nil && d.Status == types.TemporaryDocumentStatusReady }","tryCatchPattern":"file, name, err := svc.OpenFile(ctx, tenantID, sessionID, documentID)\nif err != nil && strings.Contains(err.Error(), \"attachment not found\") {\n    http.Error(w, \"attachment not found\", http.StatusNotFound)\n    return\n}","preventionTips":["Return the full lookup tuple (tenant/session/document) in errors to debug scoping mismatches","Expire client-side references when sessions end","Map this error to 404, never 500","Log tenantID with lookups to catch cross-tenant routing bugs"],"tags":["not-found","temporary-document","scoping"],"backgroundTag":"attachment-not-found","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}