{"record":{"id":"dabb5ae3e780d0bc","repo":"gastownhall/beads","slug":"iterevents-w","errorCode":null,"errorMessage":"IterEvents: %w","messagePattern":"IterEvents: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue.go","lineNumber":1857,"sourceCode":"\tout, err := u.issueRepo.CountIssuesByGroup(ctx, filter, groupBy)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"CountIssuesByGroup: %w\", err)\n\t}\n\treturn out, nil\n}\n\nfunc (u *issueUseCaseImpl) History(ctx context.Context, id string) ([]*storage.HistoryEntry, error) {\n\tout, err := u.issueRepo.History(ctx, id)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"History: %w\", err)\n\t}\n\treturn out, nil\n}\n\nfunc (u *issueUseCaseImpl) IterEvents(ctx context.Context, id string, limit int) (storage.Iter[types.Event], error) {\n\tout, err := u.issueRepo.IterEvents(ctx, id, limit)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"IterEvents: %w\", err)\n\t}\n\treturn out, nil\n}\n\nfunc (u *issueUseCaseImpl) GetStaleIssues(ctx context.Context, filter types.StaleFilter) ([]*types.Issue, error) {\n\tout, err := u.issueRepo.GetStaleIssues(ctx, filter)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"GetStaleIssues: %w\", err)\n\t}\n\treturn out, nil\n}\n\nfunc (u *issueUseCaseImpl) GetEpicsEligibleForClosure(ctx context.Context) ([]*types.EpicStatus, error) {\n\tout, err := u.issueRepo.GetEpicsEligibleForClosure(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"GetEpicsEligibleForClosure: %w\", err)\n\t}\n\treturn out, nil","sourceCodeStart":1839,"sourceCodeEnd":1875,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue.go#L1839-L1875","documentation":"This is a wrapped error from IterEvents in the issue use-case layer. The use case delegates to issueRepo.IterEvents and, if the repository returns an error, wraps it with an \"IterEvents: \" prefix before returning. The prefix identifies the failing operation while preserving the underlying cause via %w.","triggerScenarios":"Calling IterEvents(ctx, id, limit) when the underlying issueRepo.IterEvents call fails, e.g. the issue id does not exist, the database/transaction is unavailable, or a query-level error occurs.","commonSituations":"Querying an event stream for a deleted or mistyped issue id; database connection failures or Dolt errors during iteration; passing a limit the storage layer rejects.","solutions":["Inspect the wrapped underlying error with errors.Unwrap or errors.As/Is to find the real cause","Verify the issue id passed to IterEvents exists (e.g. via a Show/Get call first)","Check database connectivity and that the current transaction (if any) is still valid","Retry the call if the underlying error is transient (connection issues)"],"exampleFix":"// before\nout, err := uc.IterEvents(ctx, id, 100)\nif err != nil {\n\treturn err // loses underlying context\n}\n// after\nout, err := uc.IterEvents(ctx, id, 100)\nif err != nil {\n\tvar nfe types.ErrNotFound\n\tif errors.As(err, &nfe) {\n\t\treturn fmt.Errorf(\"issue %s not found: %w\", id, err)\n\t}\n\treturn err\n}","handlingStrategy":"try-catch","validationCode":"if id == \"\" {\n\treturn fmt.Errorf(\"issue id required before IterEvents\")\n}","typeGuard":null,"tryCatchPattern":"out, err := uc.IterEvents(ctx, id, limit)\nif err != nil {\n\tvar target error\n\tif errors.As(err, &target) { /* inspect wrapped cause */ }\n\treturn fmt.Errorf(\"listing events for %s: %w\", id, err)\n}","preventionTips":["Always check that the issue exists before iterating its events","Use errors.Is/As on the wrapped error rather than string matching the prefix","Keep retry logic at the caller for transient storage errors"],"tags":["storage","error-wrapping","events"],"backgroundTag":"repo-error-wrapping","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}