gastownhall/beads · error
reading aux rekey sentinel: %w
Error message
reading aux rekey sentinel: %w
What it means
Before running a rekey pass, rekeyAuxRowIDsPending probes the clone-local local_metadata table (via auxRekeyResumePending) to detect a crashed previous run's in-progress sentinel — a set sentinel forces resume even when the main cursor is past the shipped version. This error wraps failure of that probe (either the INFORMATION_SCHEMA table probe or the sentinel COUNT query), so the pass refuses to decide between skip and resume rather than guessing and risking a marker recorded over partially re-keyed rows.
Source
Thrown at internal/storage/schema/aux_row_id_backfill.go:233
}
}
return wrote, nil
}
func rekeyAuxRowIDsPending(ctx context.Context, db DBConn, mainVersionBefore int, pass auxRekeyPass, pending []int) (bool, error) {
markerPending := false
for _, v := range pending {
if v == pass.markerVersion {
markerPending = true
break
}
}
if !markerPending {
return false, nil
}
resume, err := auxRekeyResumePending(ctx, db, pass.sentinelKey)
if err != nil {
return false, fmt.Errorf("reading aux rekey sentinel: %w", err)
}
// The fresh-clone skip must not fire on a lineage whose previous pass
// crashed mid-rekey: that pass already advanced the main cursor past the
// shipped version, but its sentinel proves the rewrite never finished
// (bd-578h9.16).
if mainVersionBefore >= pass.shippedMainVersion && !resume {
return false, nil
}
// Sentinel before the first UPDATE: a crash anywhere in the rewrite
// leaves it set, so the next pass resumes (the rewrite is idempotent)
// instead of recording the marker over partially re-keyed rows.
if err := setAuxRekeyInProgress(ctx, db, pass.sentinelKey); err != nil {
return false, fmt.Errorf("recording aux rekey sentinel: %w", err)
}
wrote := false
for _, t := range auxRekeyTables {View on GitHub (pinned to 71377f2769)
Solutions
- Unwrap the driver error and re-run MigrateUp — the probe is read-only and safe to repeat.
- Grant SELECT on local_metadata and INFORMATION_SCHEMA access to the migration user.
- If local_metadata exists but is corrupt, drop it (it is clone-local and recreated by setAuxRekeyInProgress/EnsureIgnoredTables) and re-run.
- Check for concurrent processes holding table locks during the probe.
Defensive patterns
Strategy: retry
Validate before calling
var t int
err := db.QueryRow(`SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'local_metadata'`).Scan(&t)
if err != nil { return fmt.Errorf("cannot probe schema before migration: %w", err) } Try / catch
if err := migrateUp(ctx, db); err != nil {
if strings.Contains(err.Error(), "reading aux rekey sentinel") {
// probe failed; do NOT manually clear the sentinel — retry after fixing the DB error
return fmt.Errorf("sentinel probe failed; fix storage and re-run to resume safely: %w", err)
}
return err
} Prevention
- Grant SELECT on local_metadata and full INFORMATION_SCHEMA visibility to the migration user.
- After a crash, re-run MigrateUp promptly so the sentinel-resume path completes.
- Never DELETE the sentinel row by hand to 'unstick' a migration — the rewrite is idempotent and resume is the safe path.
- Avoid restricting INFORMATION_SCHEMA access in hardened hosting setups.
When it happens
Trigger: A pass whose marker migration is pending, while the sentinel probe queries fail: INFORMATION_SCHEMA.TABLES or local_metadata SELECT errors due to connection loss, privileges, or corruption.
Common situations: A clone resuming after a crash (sentinel path exercised) hitting a transient DB failure; permission-restricted migration user without SELECT on local_metadata; INFORMATION_SCHEMA access restricted by hosting policy.
Related errors
- recording aux rekey sentinel: %w
- %s: %w
- failed to migrate credential keys: %w
- failed to update encrypted password for peer %s: %w
- failed to initialize schema: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/2caa0e962a344e59.
Report an issue: GitHub.