gastownhall/beads · error
re-key id %s -> %s: %w
Error message
re-key id %s -> %s: %w
What it means
This error wraps a failed per-row UPDATE that rewrites an auxiliary table's `id` from an old random ID to a new deterministic content-digest-derived ID during the aux row-ID backfill. It carries both the old and new IDs plus the underlying driver error (constraint violation, connection loss, etc.). Each UPDATE is a standalone statement, so a failure mid-pass leaves the table partially re-keyed; the sentinel mechanism allows resume on the next run.
Source
Thrown at internal/storage/schema/aux_row_id_backfill.go:349
}
sort.Strings(free)
i := 0
for _, target := range targets {
if held[target] {
continue
}
todo = append(todo, rekey{oldID: free[i], newID: target})
i++
}
}
// Deterministic UPDATE order (groups is a map) so runs are reproducible.
sort.Slice(todo, func(i, j int) bool { return todo[i].oldID < todo[j].oldID })
for _, r := range todo {
//nolint:gosec // G201: table name is a hardcoded constant, never user input.
if _, err := db.ExecContext(ctx, fmt.Sprintf(`UPDATE %s SET id = ? WHERE id = ?`, t.name),
r.newID, r.oldID); err != nil {
return true, fmt.Errorf("re-key id %s -> %s: %w", r.oldID, r.newID, err)
}
}
return len(todo) > 0, nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Re-run MigrateUp: the pass is resumable via the in-progress sentinel and idempotent per digest group.
- If duplicate-key errors repeat, inspect the aux table for rows already holding the target id and remove/merge stale duplicates before rerunning.
- Confirm the table's `id` column is CHAR(36) (post-migration 0037); ensure base migrations complete first.
- Avoid concurrent writers against the database while migrations run (use the migration lock path).
Example fix
// before: one bad row aborts the whole pass
if _, err := db.ExecContext(ctx, fmt.Sprintf(`UPDATE %s SET id = ? WHERE id = ?`, t.name), r.newID, r.oldID); err != nil {
return true, fmt.Errorf("re-key id %s -> %s: %w", r.oldID, r.newID, err)
}
// after: clear any row already occupying the deterministic target id first
db.ExecContext(ctx, fmt.Sprintf(`DELETE FROM %s WHERE id = ? AND id <> ?`, t.name), r.newID, r.oldID)
if _, err := db.ExecContext(ctx, fmt.Sprintf(`UPDATE %s SET id = ? WHERE id = ?`, t.name), r.newID, r.oldID); err != nil {
return true, fmt.Errorf("re-key id %s -> %s: %w", r.oldID, r.newID, err)
} Defensive patterns
Strategy: retry
Validate before calling
// Verify the table and id column are in the expected state before migrating
var colType string
err := db.QueryRowContext(ctx,
`SELECT DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = 'id'`,
tableName).Scan(&colType)
if err == nil && colType != "char" {
return fmt.Errorf("table %s.id is %s, expected CHAR(36); run base migrations first", tableName, colType)
} Try / catch
err := migrateUp(ctx)
if err != nil && strings.Contains(err.Error(), "re-key id ") {
// partial pass is resumable; serialize writes and retry
drainWriters()
err = migrateUp(ctx)
} Prevention
- Never allow concurrent writers to the DB while migrations run; use the migration lock
- Ensure all numbered migrations (incl. 0037) complete before the aux rekey pass
- Back up the database before upgrading so a mid-pass failure is recoverable
- Re-run MigrateUp after failure — per-digest rekeying is idempotent
When it happens
Trigger: rekeyAuxRowTable executes `UPDATE <table> SET id = ? WHERE id = ?` for each pending row and the statement errors — duplicate-key conflict when the new deterministic ID already exists, connection drop, context cancellation, or the id column not being the expected CHAR(36) type.
Common situations: Digest-derived target id colliding with an existing row; migration racing concurrent writes to the aux table; database upgraded from a pre-0037 schema where `id` isn't CHAR(36); killed Dolt server mid-pass.
Related errors
- failed to scan peer for migration: %w
- failed to iterate peers for migration: %w
- failed to update encrypted password for peer %s: %w
- backfilling dependencies.id for migration 0053: %w
- counting unbackfilled dependencies.id rows for migration 005
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/48a7310a2229362c.
Report an issue: GitHub.