{"record":{"id":"563bc948d04892ca","repo":"gastownhall/beads","slug":"affected-by-batch-delete-w","errorCode":null,"errorMessage":"affected by batch delete: %w","messagePattern":"affected by batch delete: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/delete.go","lineNumber":285,"sourceCode":"\t\t\t_ = rows.Close()\n\t\t\tif err := rows.Err(); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"iterate inbound dependencies from %s: %w\", depTable, err)\n\t\t\t}\n\t\t}\n\t}\n\n\tresult.DependenciesCount = depsCount\n\tresult.LabelsCount = labelsCount\n\tresult.EventsCount = eventsCount\n\tresult.DeletedCount = len(set.RegularIDs) + len(set.WispIDs)\n\n\tif dryRun {\n\t\treturn result, nil\n\t}\n\n\taffectedIssues, affectedWisps, aerr := AffectedByDeletionInTx(ctx, tx, set.RegularIDs, set.WispIDs)\n\tif aerr != nil {\n\t\treturn nil, fmt.Errorf(\"affected by batch delete: %w\", aerr)\n\t}\n\n\t// Resolve WHICH regular ids this delete actually removes before the batched\n\t// DELETE runs: afterwards the rows are gone, and RowsAffected reports a\n\t// count, not a set. A journal record for an id that was already absent would\n\t// tell a consumer to drop a bead this transaction never touched.\n\tjournaledDeletes, err := journalableDeletesInTx(ctx, tx, \"issues\", set.RegularIDs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// Edges are journaled before the rows go, while their source snapshots can\n\t// still be read.\n\tif err := RecordDependencyRemovalsForIssuesInTx(ctx, tx, set.All); err != nil {\n\t\treturn nil, fmt.Errorf(\"journal dependency removals for batch delete: %w\", err)\n\t}\n\n\tfor _, id := range set.WispIDs {\n\t\tif err := deleteIssueRowInTx(ctx, tx, id, true); err != nil {","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/delete.go#L267-L303","documentation":"DeleteResolvedSetInTx aborts when AffectedByDeletionInTx — which computes which remaining issues would become blocked or orphaned by this deletion — fails. The wrapped error comes from that blocked-state analysis query set. This runs in dry-run mode and before actual deletes, so nothing has been removed yet when it fires.","triggerScenarios":"Calling DeleteIssuesInTx/DeleteInTx when the blocked-state analysis queries fail: missing blocked-state tables, connection failure, context cancellation, or a driver that can't execute the affected-set SQL.","commonSituations":"Alternative/embedded drivers lacking the SQL surface AffectedByDeletionInTx needs; schema drift removing blocked-state structures; timeouts on repos with huge dependency graphs.","solutions":["Unwrap the error for the specific query that failed inside the analysis.","Verify the backend implements the full driver interface including blocked-state analysis.","Retry on a fresh transaction; safe because nothing was deleted yet.","Run schema migrations if blocked-state tables are missing."],"exampleFix":"// before\nres, err := store.DeleteInTx(ctx, tx, ids)\n// after\nres, err := store.DeleteInTx(ctx, tx, ids)\nif err != nil {\n    return fmt.Errorf(\"no rows deleted (analysis failed first): %w\", err)\n}","handlingStrategy":"validation","validationCode":"// blocked-state analysis is part of the driver surface; verify support first\nif !driver.Supports(ctx, driver.FeatureBlockedStateAnalysis) {\n    return errors.New(\"backend does not support blocked-state analysis required for delete\")\n}","typeGuard":null,"tryCatchPattern":"res, err := store.DeleteInTx(ctx, tx, ids)\nif err != nil && strings.Contains(err.Error(), \"affected by batch delete\") {\n    return fmt.Errorf(\"pre-delete analysis failed, nothing was deleted (safe to retry): %w\", err)\n}","preventionTips":["Use backends passing the conformance deleter contract.","Run schema migrations before deleting.","Remember this fires before any mutation — a failure here never leaves partial deletes."],"tags":["go","storage","transaction","blocked-state","batch-delete"],"backgroundTag":"sql-count-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}