{"record":{"id":"a12145c06f81302b","repo":"gastownhall/beads","slug":"delete-check-dependents-w-a12145","errorCode":null,"errorMessage":"delete: check dependents: %w","messagePattern":"delete: check dependents: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/uow/deleter.go","lineNumber":218,"sourceCode":"\tdepUC := uw.DependencyUseCase()\n\tbySource := make(map[string]map[string]bool)\n\n\tfor _, plane := range []struct {\n\t\tlist     func(context.Context, []string, domain.DepListFilter) (domain.DepBulkResult, error)\n\t\toptional bool\n\t}{\n\t\t{list: depUC.ListByIssueIDs},\n\t\t// The wisp plane is optional the way every other cross-plane read here\n\t\t// treats it: a workspace whose schema predates it has no table, and\n\t\t// that is not a failed guard.\n\t\t{list: depUC.ListByWispIDs, optional: true},\n\t} {\n\t\tres, err := plane.list(ctx, ids, domain.DepListFilter{Direction: domain.DepDirectionIn})\n\t\tif err != nil {\n\t\t\tif plane.optional && dberrors.IsTableNotExist(err) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"delete: check dependents: %w\", err)\n\t\t}\n\t\tfor target, edges := range res.Incoming {\n\t\t\tfor _, edge := range edges {\n\t\t\t\tif edge == nil || idSet[edge.IssueID] {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif bySource[target] == nil {\n\t\t\t\t\tbySource[target] = make(map[string]bool)\n\t\t\t\t}\n\t\t\t\tbySource[target][edge.IssueID] = true\n\t\t\t}\n\t\t}\n\t}\n\n\tout := make(map[string][]string, len(bySource))\n\tfor target, dependents := range bySource {\n\t\tout[target] = workapi.SortedDeleteIDs(dependents)\n\t}","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/uow/deleter.go#L200-L236","documentation":"While collecting external dependents before a delete, one of the per-plane dependency listing queries (incoming edges) failed. Only optional planes with a 'table does not exist' error are skipped; any other failure aborts the delete with this wrapped error, leaving the delete unperformed.","triggerScenarios":"externalDependentsBySourceInUOW calls plane.list with DepListFilter{Direction: In} for each plane; a non-optional plane's query fails, or an optional plane fails with an error other than IsTableNotExist — DB error, connection loss, permission failure, schema drift.","commonSituations":"Database degradation during delete (timeout, restart); schema drift where a dependency table exists but is broken (not cleanly 'not exist'); permissions revoked on the dependency tables.","solutions":["Fix the underlying DB error reported by the wrapped cause, then retry the delete","If a plane's table is genuinely gone but the error is not classified as TableNotExist, repair the schema (bd doctor/migrations) so it is detected or recreated","Verify DB privileges for the dependency tables","Retry after transient connectivity issues"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check which planes' dep tables exist before deleting\nfor _, t := range []string{\"issue_dependencies\", \"wisp_dependencies\"} {\n    if !tableExists(ctx, db, t) { /* treat as empty plane */ }\n}","typeGuard":"func isDependentCheckFailure(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"delete: check dependents\")\n}","tryCatchPattern":"res, err := deleteInUOW(ctx, req)\nif isDependentCheckFailure(err) {\n    if dberrors.IsTableNotExist(errors.Unwrap(err)) { /* optional plane missing: proceed */ }\n    return fmt.Errorf(\"cannot verify dependents; delete aborted: %w\", err)\n}","preventionTips":["Keep schema migrations current so optional-plane tables either exist cleanly or are absent","Check DB privileges on dependency tables before bulk deletes","Treat this error as abort-with-no-changes and fix the DB before retrying","Run 'bd doctor' when unsure of schema state"],"tags":["database","delete","dependencies","dependents"],"backgroundTag":"dependent-check-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}