{"record":{"id":"e6b22fc3716575f7","repo":"gastownhall/beads","slug":"w-issue-s-e6b22f","errorCode":null,"errorMessage":"%w: issue %s","messagePattern":"%w: issue (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/uow/issue_operations.go","lineNumber":508,"sourceCode":"\n// operationIssue resolves id to the row an operation is about. Both planes are\n// searched unless issuePlaneOnly restricts it, in which case a wisp id is a\n// miss rather than an ephemeral row to operate on. Every call runs inside the\n// operation's own transaction.\nfunc operationIssue(ctx context.Context, uw UnitOfWork, id string, issuePlaneOnly bool) (*types.Issue, bool, error) {\n\tif !issuePlaneOnly {\n\t\tissue, err := uw.IssueUseCase().GetWisp(ctx, id)\n\t\tif err == nil && issue != nil {\n\t\t\treturn issue, true, nil\n\t\t}\n\t\tif err != nil && !errors.Is(err, publicops.ErrNotFound) && !dberrors.IsNoRows(err) {\n\t\t\treturn nil, false, fmt.Errorf(\"read wisp %s: %w\", id, err)\n\t\t}\n\t}\n\tissue, err := uw.IssueUseCase().GetIssue(ctx, id)\n\tif err != nil {\n\t\tif errors.Is(err, publicops.ErrNotFound) || dberrors.IsNoRows(err) {\n\t\t\treturn nil, false, fmt.Errorf(\"%w: issue %s\", publicops.ErrNotFound, id)\n\t\t}\n\t\treturn nil, false, err\n\t}\n\tif issue == nil {\n\t\treturn nil, false, fmt.Errorf(\"%w: issue %s\", publicops.ErrNotFound, id)\n\t}\n\treturn issue, false, nil\n}\n\nfunc validationError(err error) error {\n\tif errors.Is(err, publicops.ErrValidation) {\n\t\treturn err\n\t}\n\treturn fmt.Errorf(\"%w: %w\", publicops.ErrValidation, err)\n}\n\nfunc validateUpdateRequest(request publicops.UpdateRequest) error {\n\tif request.Actor == \"\" || request.IssueID == \"\" {","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/uow/issue_operations.go#L490-L526","documentation":"When neither the wisp read nor the durable GetIssue finds the issue (ErrNotFound or no-rows), operationIssue returns publicops.ErrNotFound wrapped with the issue ID. It is the library's canonical 'issue does not exist' signal for update/close/reopen paths.","triggerScenarios":"Updating, closing, reopening, or hydrating an issue ID that does not exist: GetIssue returned ErrNotFound or dberrors.IsNoRows(err) is true, or the wisp read already said not-found.","commonSituations":"Typo'd issue key (e.g. bd-1234 vs bd-1243), issue already deleted by another process, operating against a different database/branch than the one holding the issue, stale ID from an old export.","solutions":["Verify the issue ID is correct (list issues to confirm it exists)","Check you are pointed at the right database (path, branch, remote)","If the ID came from another system, re-fetch it rather than caching","Handle publicops.ErrNotFound via errors.Is in the caller instead of retrying"],"exampleFix":"// before: string matching on the error\nif strings.Contains(err.Error(), \"not found\") { ... }\n// after\nif errors.Is(err, publicops.ErrNotFound) {\n    // handle missing issue\n}","handlingStrategy":"type-guard","validationCode":"// Confirm existence before update/close/reopen\nif _, err := uc.GetIssue(ctx, id); errors.Is(err, publicops.ErrNotFound) { return fmt.Errorf(\"issue %s missing\", id) }","typeGuard":"func isIssueNotFound(err error) bool {\n    return errors.Is(err, publicops.ErrNotFound) || dberrors.IsNoRows(err)\n}","tryCatchPattern":"if err := uc.Update(ctx, req); err != nil {\n    if isIssueNotFound(err) {\n        // issue absent: skip, or recreate\n        return nil\n    }\n    return err\n}","preventionTips":["Fetch issue IDs from list output instead of hand-typing keys","Confirm you are pointed at the correct database/branch","Never cache issue IDs across exports or DB resets","Use errors.Is against publicops.ErrNotFound, never string matching"],"tags":["not-found","issue-lookup","go","sentinel-error"],"backgroundTag":"issue-not-found","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}