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

  1. Unwrap the driver error and re-run MigrateUp — the probe is read-only and safe to repeat.
  2. Grant SELECT on local_metadata and INFORMATION_SCHEMA access to the migration user.
  3. If local_metadata exists but is corrupt, drop it (it is clone-local and recreated by setAuxRekeyInProgress/EnsureIgnoredTables) and re-run.
  4. 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

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


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