gastownhall/beads · warning
wake expired defer %s rows affected: %w
Error message
wake expired defer %s rows affected: %w
What it means
Thrown when res.RowsAffected() fails after a successful wake UPDATE. Some drivers cannot report rows affected (unsupported statement type, driver limitation, or broken connection), making it impossible to tell whether the row was actually woken. The function conservatively returns the error, though the UPDATE itself succeeded.
Source
Thrown at internal/storage/issueops/wake_defers.go:126
var woken []string
now := time.Now().UTC()
for _, id := range expired {
// row_lock is rewritten so a concurrent claim/update conflicts at
// commit time instead of cell-merging with this write — the same
// invariant the lease scheme depends on.
//nolint:gosec // G201: table is a hardcoded constant from the caller above.
res, err := tx.ExecContext(ctx, fmt.Sprintf(`
UPDATE %s
SET status = 'open', defer_until = NULL, updated_at = ?, row_lock = ?
WHERE id = ? AND status = 'deferred' AND defer_until IS NOT NULL
AND defer_until <= UTC_TIMESTAMP()
`, table), now, freshRowLock(), id)
if err != nil {
return woken, fmt.Errorf("wake expired defer %s: %w", id, err)
}
n, err := res.RowsAffected()
if err != nil {
return woken, fmt.Errorf("wake expired defer %s rows affected: %w", id, err)
}
if n == 0 {
continue // rescued concurrently — leave it be
}
if err := RecordFullEventInTable(ctx, tx, eventsTable, id, types.EventStatusChanged,
DeferWakeActor, string(types.StatusDeferred), string(types.StatusOpen)); err != nil {
return woken, fmt.Errorf("record wake event for %s: %w", id, err)
}
// A wake is a status change, so it journals as an update. Emitted past
// the rows-affected re-check, so a concurrently-rescued bead records
// nothing.
if err := RecordEventInTx(ctx, tx, EventUpdate, id, DeferWakeActor); err != nil {
return woken, err
}
woken = append(woken, id)
}
return woken, nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped cause; if it is a driver capability gap, upgrade the driver/Dolt server.
- Retry the operation — the guarded UPDATE means concurrent rescues are harmlessly skipped.
- If using a proxy or unusual MySQL-compatible backend, verify it forwards the affected-rows count.
- As a last resort, log and continue (n unknown) only if your deployment tolerates unreported wake events.
Example fix
// before: incomplete driver
import "github.com/legacy/go-mysql-driver"
// after
db, err := sql.Open("mysql", dsn) // official go-sql-driver/mysql with full RowsAffected support Defensive patterns
Strategy: fallback
Validate before calling
// verify driver supports RowsAffected
rows, err := db.Exec("UPDATE issues SET updated_at=updated_at WHERE id=(SELECT id FROM issues LIMIT 1)")
if err != nil { return err }
if _, err := rows.RowsAffected(); err != nil { log.Print("driver lacks RowsAffected support; upgrade driver") } Try / catch
if err != nil {
log.Printf("RowsAffected unavailable for %s; treating as best-effort wake: %v", id, err)
continue // UPDATE succeeded; only the count is unknown
} Prevention
- Use the official go-sql-driver/mysql or a fully-featured Dolt driver.
- Avoid MySQL proxies/backends that strip the affected-rows response.
- Upgrade the storage driver when RowsAffected errors appear.
- Test RowsAffected support during deployment smoke checks.
When it happens
Trigger: Calling WakeExpiredDefersInTx against a driver/backend that does not implement RowsAffected for UPDATE statements, or whose connection died between the UPDATE response and the metadata read.
Common situations: Using a minimal/proxy MySQL driver or Dolt version with incomplete RowsAffected support; transaction connection aborted mid-statement.
Related errors
- failed to check rows affected for issue counter prefix %q: %
- failed to check rows affected after seeding for prefix %q: %
- db: DependencySQLRepository.DeleteAllForIDs rows affected: %
- db: EventsSQLRepository.DeleteAllForIDs rows affected: %w
- db: Update %s: rows affected: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0d9d5f3771dee321.
Report an issue: GitHub.