gastownhall/beads · error
failed to read assignee/status for %s: %w
Error message
failed to read assignee/status for %s: %w
What it means
CheckExpectedFieldsInTx wraps any non-no-rows database error from reading assignee/status with this message. It means the precondition check itself could not run — not that a field mismatched — so the CAS update is aborted rather than silently proceeding unguarded.
Source
Thrown at internal/storage/issueops/update_cas.go:50
//
//nolint:gosec // G201: table name comes from WispTableRouting (hardcoded constants)
func CheckExpectedFieldsInTx(ctx context.Context, tx DBTX, id string, expectedAssignee, expectedStatus *string) error {
if expectedAssignee == nil && expectedStatus == nil {
return nil
}
isWisp := IsActiveWispInTx(ctx, tx, id)
issueTable, _, _, _ := WispTableRouting(isWisp)
var assignee sql.NullString
var status string
err := tx.QueryRowContext(ctx,
fmt.Sprintf("SELECT assignee, status FROM %s WHERE id = ?", issueTable), id,
).Scan(&assignee, &status)
if errors.Is(err, sql.ErrNoRows) {
return fmt.Errorf("%w: issue %s", storage.ErrNotFound, id)
}
if err != nil {
return fmt.Errorf("failed to read assignee/status for %s: %w", id, err)
}
if expectedAssignee != nil && !actorMatches(assignee.String, *expectedAssignee) {
return fmt.Errorf("%w: %s is held by %q, expected %q", storage.ErrAssigneeMismatch, id, assignee.String, *expectedAssignee)
}
if expectedStatus != nil && status != *expectedStatus {
return fmt.Errorf("%w: %s has status %q, expected %q", storage.ErrStatusMismatch, id, status, *expectedStatus)
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped %w cause to identify the driver-level failure
- Retry the operation if the error is transient (connection reset, lock wait timeout)
- Run schema checks/migrations to confirm assignee and status columns exist
- Verify DB credentials and grants for the issuing process
Defensive patterns
Strategy: retry
Validate before calling
// verify schema/connectivity first
row := db.QueryRow("SELECT assignee, status FROM issues WHERE id = ?", id)
if err := row.Err(); err != nil { return err } Try / catch
err := ExecuteUpdate(ctx, tx, id, updates, exp)
if err != nil && !errors.Is(err, storage.ErrNotFound) &&
!errors.Is(err, storage.ErrAssigneeMismatch) && !errors.Is(err, storage.ErrStatusMismatch) {
return retryWithBackoff(op) // transient read failure
} Prevention
- Use connection retry/backoff around transactions
- Keep schema migrations current so assignee/status columns exist
- Grant the app role SELECT on issues; monitor DB health
When it happens
Trigger: ExecuteUpdate with ExpectedFields while the underlying SELECT assignee,status FROM issues WHERE id=? fails due to connection loss, lock timeouts, permission denial, or schema drift (missing columns).
Common situations: DB restarted or network blip mid-transaction; migrations removed/renamed assignee or status columns; insufficient DB user grants; Dolt server overload causing query timeouts.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- db: CommentSQLRepository.InsertRecord: check issue existence
- db: GetMetadata %s: %w
- failed to read row version for %s: %w
- ErrTransaction
- ErrQuery
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/5d9873cdd827afdc.
Report an issue: GitHub.