gastownhall/beads · error

rekey aux row ids: %w

Error message

rekey aux row ids: %w

What it means

This error wraps a failure in rekeyAuxRowIDsAllPasses, the multi-pass rewrite that converges randomized primary keys on events/comments/snapshots tables (bd-6dnrw.2 and bd-ri8bd). Like the dependency rekey, it fires mid-pass after main migrations applied, so the returned applied count reflects work already done and the database may be mid-rewrite.

Source

Thrown at internal/storage/schema/schema.go:689

	if err != nil {
		return applied, fmt.Errorf("rekey dependency ids: %w", err)
	}
	backfilled = backfilled || rekeyed

	// bd-6dnrw.2: converge the events/comments/snapshots primary keys that
	// migration 0037 randomized per-clone, the same hazard class on the aux
	// tables. Gated on the clone-local ignored marker (recorded later in this
	// pass by ignoredSource.migrate) so it runs exactly once per clone instead
	// of churning synced rows on every later migration pass — and on the
	// pre-pass main cursor, so fresh clones of converged lineages record the
	// marker without re-running the rewrite (bd-578h9.4).
	// ...and the bd-ri8bd sibling: one more pass over the same tables for the
	// rows minted with random UUIDv7 ids between the initial backfill and the
	// switch to content-derived ids at insert time. Same machinery, own
	// marker/sentinel/shipped-version gates, one shared cursor read.
	auxRekeyed, err := rekeyAuxRowIDsAllPasses(ctx, db, mainVersionBefore)
	if err != nil {
		return applied, fmt.Errorf("rekey aux row ids: %w", err)
	}
	backfilled = backfilled || auxRekeyed

	touchedIgnoredDirtyTables, err := ignoredSource.pendingMigrationDirtyTables(ctx, db, dirtyBeforeAll)
	if err != nil {
		return applied, fmt.Errorf("checking dirty tables against pending ignored migrations: %w", err)
	}
	if len(touchedIgnoredDirtyTables) > 0 {
		// Deliberately a plain, untyped error (unlike the main-source guard
		// above, which returns *DirtyTablesError): this check fires mid-pass,
		// after the main-source migrations have already applied. A lenient
		// caller (embeddeddolt's openReadOnlyCommand / openWorkingSetReconcile
		// intents) skipping this and returning as if the open succeeded would
		// let a reconcile commit checkpoint a half-applied migration pass.
		// The ignored source also tracks bd-internal state (dolt_ignore'd
		// tables like ignored_schema_migrations), not expected user data, so
		// there is no dirty-commit recovery story to support here the way
		// there is for the main-source guard (#4566 scope).

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped cause; a resume-pending sentinel means re-running MigrateUp should continue the interrupted rekey
  2. Resolve duplicate ids or constraint violations surfaced by the wrapped error, then re-run
  3. Avoid killing the process mid-pass; run migrations with the advisory lock (MigrateUpWithLock)
  4. If the working set is stuck dirty from a partial pass, restore from the last Dolt commit and retry
Defensive patterns

Strategy: retry

Validate before calling

// Check for a pending resume sentinel indicating an interrupted rekey
// (resuming is expected and safe; just ensure storage is writable first)
if _, err := db.ExecContext(ctx, "SELECT 1"); err != nil {
    return fmt.Errorf("storage not writable for rekey resume: %w", err)
}

Type guard

func isAuxRekeyErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "rekey aux row ids")
}

Try / catch

applied, err := schema.MigrateUp(ctx, db)
if isAuxRekeyErr(err) {
    // rekey passes are resumable: retry after fixing the wrapped cause
    return schema.MigrateUp(ctx, db)
}

Prevention

When it happens

Trigger: Calling MigrateUp/MigrateUpWithLock where the aux rekey passes fail - duplicate content-derived keys on events/comments/snapshots, resume-sentinel state corruption from a previous crash (bd-578h9.16), or Dolt write errors during the batched UPDATEs.

Common situations: Crashed earlier passes leaving partial aux rekey updates; clones with rows minted between the backfill and the content-id switch; very large event tables hitting timeouts/storage limits mid-pass.

Related errors


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