gastownhall/beads · warning

clearing aux rekey sentinel: %w

Error message

clearing aux rekey sentinel: %w

What it means

This error wraps a failure to delete the 'aux rekey in progress' sentinel row from local_metadata after an auxiliary-table ID re-key pass completes. The rekey already finished; only the cleanup DELETE failed, so the sentinel remains and the next migration run will resume/re-run the pass. It indicates a write failure against the local_metadata table (connection loss, lock timeout, permissions, or cancellation) at the very end of a migration pass.

Source

Thrown at internal/storage/schema/aux_row_id_backfill.go:259

	}

	// 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 {
		w, err := rekeyAuxRowTable(ctx, db, t)
		wrote = wrote || w
		if err != nil {
			return wrote, fmt.Errorf("%s: %w", t.name, err)
		}
	}
	if err := clearAuxRekeyInProgress(ctx, db, pass.sentinelKey); err != nil {
		return wrote, fmt.Errorf("clearing aux rekey sentinel: %w", err)
	}
	return wrote, nil
}

// rekeyAuxRowTable re-derives the ids of one table. The whole table is grouped
// by content digest; each digest's rows take the deterministic ids for
// ordinals 0..n-1. A row already holding one of its group's target ids keeps
// it (idempotence: re-running never swaps ids within a group), and the
// remaining rows take the remaining targets in sorted-current-id order. Across
// clones that assignment may permute within a group of exact-duplicate rows,
// but duplicates are interchangeable and the id set is identical, so the
// merged result still converges.
func rekeyAuxRowTable(ctx context.Context, db DBConn, t auxRekeyTable) (bool, error) {
	// Skip cleanly if the table or its id column isn't present (older or partial
	// schema): nothing to re-key. After MigrateUp's main pass the id column is
	// CHAR(36) on any schema this runs against (0037 precedes the marker).
	hasID, err := columnExists(ctx, db, t.name, "id")
	if err != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run the migration (MigrateUp re-invokes the pass because the sentinel is still set; the rekey is idempotent and will converge and clear the sentinel this time).
  2. Check DB connectivity and that the Dolt server is up, then retry.
  3. Verify the DB user has DELETE privilege on local_metadata.
  4. Check the context isn't being cancelled prematurely by the caller (timeouts, signal handling).

Example fix

// before: sentinel left behind after transient DELETE failure
if err := clearAuxRekeyInProgress(ctx, db, pass.sentinelKey); err != nil {
	return wrote, fmt.Errorf("clearing aux rekey sentinel: %w", err)
}
// after: best-effort cleanup, sentinel is safe to resume next run
if err := clearAuxRekeyInProgress(ctx, db, pass.sentinelKey); err != nil {
	log.Printf("warning: clearing aux rekey sentinel %s: %v (will resume next run)", pass.sentinelKey, err)
}
Defensive patterns

Strategy: retry

Validate before calling

// Before triggering migration, check the sentinel table is accessible
var n int
if err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM local_metadata").Scan(&n); err != nil {
	return fmt.Errorf("local_metadata not accessible: %w", err)
}

Try / catch

result, err := runMigration(ctx)
if err != nil && strings.Contains(err.Error(), "clearing aux rekey sentinel") {
	// cleanup-only failure: re-run; the pass is idempotent and will clear the sentinel
	result, err = runMigration(context.Background())
}

Prevention

When it happens

Trigger: rekeyAuxRowIDsPending calls clearAuxRekeyInProgress (DELETE FROM local_metadata WHERE key = <sentinelKey>) after the rekey pass succeeds; the DELETE fails due to a dropped/cancelled context, DB connection loss, insufficient privileges on local_metadata, or a lock conflict during migration.

Common situations: Network blip or Dolt server restart mid-migration; context cancelled by the user Ctrl-C'ing a long `bd` migration; local_metadata table locked by another session; running with a DB user lacking DELETE privilege.

Related errors


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