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

  1. Inspect the wrapped %w cause to identify the driver-level failure
  2. Retry the operation if the error is transient (connection reset, lock wait timeout)
  3. Run schema checks/migrations to confirm assignee and status columns exist
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/5d9873cdd827afdc. Report an issue: GitHub.