{"record":{"id":"3bf3ca6c3d4d2a03","repo":"gastownhall/beads","slug":"delete-leases-w","errorCode":null,"errorMessage":"delete leases: %w","messagePattern":"delete leases: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/bulk_ops.go","lineNumber":204,"sourceCode":"\t\t}\n\t\tissueIDs = append(issueIDs, id)\n\t}\n\t_ = rows.Close()\n\n\tif len(issueIDs) == 0 {\n\t\treturn 0, nil\n\t}\n\n\taffectedIssues, affectedWisps, aerr := AffectedByDeletionInTx(ctx, tx, issueIDs, nil)\n\tif aerr != nil {\n\t\treturn 0, fmt.Errorf(\"affected by source-repo delete: %w\", aerr)\n\t}\n\n\t// Deleted issues hold no leases: clear them while the id set is still\n\t// joinable (before the issues rows go away).\n\tif _, err := tx.ExecContext(ctx,\n\t\t`DELETE FROM leases WHERE issue_id IN (SELECT id FROM issues WHERE source_repo = ?)`, sourceRepo); err != nil {\n\t\treturn 0, fmt.Errorf(\"delete leases: %w\", err)\n\t}\n\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, issueIDs); err != nil {\n\t\treturn 0, fmt.Errorf(\"journal dependency removals for source-repo delete: %w\", err)\n\t}\n\n\tresult, err := tx.ExecContext(ctx, `DELETE FROM issues WHERE source_repo = ?`, sourceRepo)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"delete issues: %w\", err)\n\t}\n\n\trowsAffected, err := result.RowsAffected()\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"rows affected: %w\", err)\n\t}\n","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/bulk_ops.go#L186-L222","documentation":"The function clears leases belonging to the doomed issues with a DELETE FROM leases subquery; a failure is wrapped as \"delete leases: %w\". It fires when the lease rows cannot be removed inside the transaction.","triggerScenarios":"tx.ExecContext on `DELETE FROM leases WHERE issue_id IN (SELECT ...)` fails: leases table missing, database locked by another writer, foreign-key constraint from another table referencing leases, or context canceled.","commonSituations":"Older schema without a leases table; concurrent process (another bd instance or agent) holding a write lock; disk-full or read-only filesystem surfacing as a driver write error.","solutions":["Read the wrapped driver error (no such table / database is locked / readonly)","Migrate the schema if the leases table is absent","Ensure no other process holds a write lock; retry the transaction after the contention clears","Check filesystem permissions and free space"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// ensure leases table exists and FS is writable before deleting\n_, err := db.Exec(\"SELECT 1 FROM leases LIMIT 1\")","typeGuard":"if errors.Is(err, sqlite.ErrBusy) || strings.Contains(err.Error(), \"database is locked\") { /* lock contention */ }","tryCatchPattern":"if err := DeleteIssuesBySourceRepoInTx(ctx, tx, repo); err != nil {\n    if strings.Contains(err.Error(), \"delete leases\") {\n        // check concurrent writers, then retry the transaction\n    }\n    return err\n}","preventionTips":["Ensure a single bd process owns write access during bulk ops","Check disk space and read-only mounts before destructive operations","Migrate schema so leases exists before running newer versions"],"tags":["database","sql-delete","locking"],"backgroundTag":"database-locked","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}