{"record":{"id":"d82a248bdccbe538","repo":"gastownhall/beads","slug":"hydrate-neighbors-issues-w","errorCode":null,"errorMessage":"hydrate neighbors (issues): %w","messagePattern":"hydrate neighbors \\(issues\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue_delete.go","lineNumber":381,"sourceCode":"\t\t\t}\n\t\t}\n\t}\n\taccumulate(issueRes.Outgoing)\n\taccumulate(issueRes.Incoming)\n\taccumulate(wispRes.Outgoing)\n\taccumulate(wispRes.Incoming)\n\n\tif len(neighbors) == 0 {\n\t\treturn out, isWisp, nil\n\t}\n\tids := make([]string, 0, len(neighbors))\n\tfor id := range neighbors {\n\t\tids = append(ids, id)\n\t}\n\n\tfromIssues, err := u.issueRepo.GetByIDs(ctx, ids, IssueTableOpts{})\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"hydrate neighbors (issues): %w\", err)\n\t}\n\tfor _, iss := range fromIssues {\n\t\tout[iss.ID] = iss\n\t}\n\tfromWisps, err := u.issueRepo.GetByIDs(ctx, ids, IssueTableOpts{UseWispsTable: true})\n\tif err != nil && !dberrors.IsTableNotExist(err) {\n\t\treturn nil, nil, fmt.Errorf(\"hydrate neighbors (wisps): %w\", err)\n\t}\n\tfor _, iss := range fromWisps {\n\t\tout[iss.ID] = iss\n\t\tisWisp[iss.ID] = true\n\t}\n\treturn out, isWisp, nil\n}\n\nfunc (u *issueUseCaseImpl) rewriteTextReferences(\n\tctx context.Context, deletedIDs []string,\n\tconnected map[string]*types.Issue, isWisp map[string]bool, actor string,","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue_delete.go#L363-L399","documentation":"This error wraps a failure from issueRepo.GetByIDs while hydrating the neighbor issues discovered during a connected-delete traversal. collectConnectedIssues first collects dependency edges, then bulk-loads the actual issue rows for the neighbor IDs from the durable `issues` table. If that bulk fetch fails (DB error, corruption, context cancel), the delete/preview operation aborts with this wrapped message.","triggerScenarios":"Calling deleteMany or previewDelete when the batch has dependency neighbors, and the GetByIDs query against the durable issues table fails — e.g. database closed/locked, connection dropped, context canceled mid-query, or a storage driver error.","commonSituations":"Deleting a batch of issues over an unstable Dolt/embedded DB connection; canceling a long-running bd delete; a corrupted or partially-migrated database where the issues table is unreadable; hitting a driver-level timeout during bulk hydration.","solutions":["Check the wrapped cause (%w) for the underlying driver/SQL error and fix that first (connection, lock, corruption).","Verify the database is reachable and not locked by another process (e.g. another bd session holding a write lock).","Retry the delete/preview with a fresh, uncanceled context; ensure no caller cancels ctx mid-operation.","If corruption is suspected, run bd doctor / repair the store, then retry.","Confirm the neighbor IDs collected are valid (no empty/garbage IDs) — malformed IDs can surface as query errors."],"exampleFix":"// before: cancelable request ctx flows into a long delete\ndeleter.DeleteMany(ctx, ids)\n\n// after: use an operation-scoped context with timeout for the delete\nopCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\ndefer cancel()\ndeleteErr := deleter.DeleteMany(opCtx, ids)","handlingStrategy":"try-catch","validationCode":"// before deleting, confirm the DB is reachable and ids are non-empty\nif len(ids) == 0 { return errors.New(\"no ids to delete\") }\nif err := db.PingContext(ctx); err != nil { return fmt.Errorf(\"store unreachable: %w\", err) }","typeGuard":"func isHydrateNeighborsErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"hydrate neighbors (issues)\")\n}","tryCatchPattern":"err := usecase.DeleteMany(ctx, ids)\nif err != nil {\n    var wrapped interface{ Unwrap() error }\n    if strings.Contains(err.Error(), \"hydrate neighbors (issues)\") {\n        // retry after checking connectivity; underlying cause via errors.Unwrap\n    }\n    return err\n}","preventionTips":["Run deletes with a dedicated long-timeout context, not a request-scoped one","Avoid concurrent bd writers on the same store","Ping the database / check store health before bulk deletes","Validate all IDs are non-empty and well-formed before the call"],"tags":["storage","database","delete","hydration"],"backgroundTag":"database-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}