gastownhall/beads · error
adding wisp_dependencies.id for the 0058 repair: %w
Error message
adding wisp_dependencies.id for the 0058 repair: %w
What it means
Wraps a failure when adding the final surrogate key column to wisp_dependencies (`ALTER TABLE ... ADD COLUMN id CHAR(36) NOT NULL DEFAULT (UUID()) PRIMARY KEY FIRST`) when the id column is missing. This is the first step of the final 0058 shape; a failure leaves the table without its primary identity, so the repair aborts.
Source
Thrown at internal/storage/schema/wisp_dep_forward_repair.go:400
// composite-keyed shape without one, and ignored/0005 -- the only migration that
// adds id to a legacy store -- drops the generated column in the same guarded
// run. There is no state carrying both, so this never has to reconcile one.
//
// DEFAULT (UUID()) is correct here even though a fully migrated table carries
// no default: ignored/0010 drops it, and this repair can only reach the ADD
// COLUMN branch on a store whose ignored cursor is still behind 0005 (that is
// what "the generated column is still present" means), hence behind 0010. The
// default is therefore always dropped downstream in the same pass, which is why
// ignored/0005 mints the column the same way rather than special-casing it.
func ensureWispDepSurrogateKey(ctx context.Context, db DBConn) error {
hasID, err := schemaColumnExists(ctx, db, wispDepTable, "id")
if err != nil {
return err
}
if !hasID {
if _, err := db.ExecContext(ctx,
"ALTER TABLE wisp_dependencies ADD COLUMN id CHAR(36) NOT NULL DEFAULT (UUID()) PRIMARY KEY FIRST"); err != nil {
return fmt.Errorf("adding wisp_dependencies.id for the 0058 repair: %w", err)
}
return nil
}
// id survived a crash but its key did not (or the column predates the
// key): add the key alone rather than re-adding the column.
hasPK, err := schemaHasPrimaryKey(ctx, db, wispDepTable)
if err != nil {
return err
}
if !hasPK {
if _, err := db.ExecContext(ctx, "ALTER TABLE wisp_dependencies ADD PRIMARY KEY (id)"); err != nil {
return fmt.Errorf("adding the wisp_dependencies id primary key for the 0058 repair: %w", err)
}
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped cause: unsupported DEFAULT (UUID()) → upgrade Dolt/MySQL to a version supporting expression defaults.
- Re-run the guarded repair after fixing the engine/privilege issue.
- Grant ALTER (and privilege to evaluate UUID backfill) to the migration user.
- Retry during a maintenance window with no concurrent writers on wisp_dependencies.
Example fix
// before: fails on engines without expression defaults ALTER TABLE wisp_dependencies ADD COLUMN id CHAR(36) NOT NULL DEFAULT (UUID()) PRIMARY KEY FIRST // after: upgrade the engine, or add then backfill manually ALTER TABLE wisp_dependencies ADD COLUMN id CHAR(36) NULL FIRST; UPDATE wisp_dependencies SET id = UUID() WHERE id IS NULL; ALTER TABLE wisp_dependencies MODIFY id CHAR(36) NOT NULL, ADD PRIMARY KEY (id);
Defensive patterns
Strategy: try-catch
Validate before calling
// verify engine supports functional column defaults before repair
var version string
if err := db.QueryRowContext(ctx, "SELECT VERSION()").Scan(&version); err != nil {
log.Fatalf("cannot read engine version: %v", err)
}
log.Printf("engine %s — DEFAULT (UUID()) requires MySQL 8.0.13+/current Dolt", version) Try / catch
if err := repairWispDependenciesForwardShape(ctx, db); err != nil {
if strings.Contains(err.Error(), "adding wisp_dependencies.id") {
// likely expression-default unsupported or privilege denial; upgrade engine or add+backfill id manually, then re-run
return fmt.Errorf("surrogate key step failed; check engine version/privileges: %w", err)
}
return err
} Prevention
- Run a Dolt/MySQL version supporting DEFAULT (UUID()) expression defaults.
- Grant ALTER to the migration user.
- Run the repair with no concurrent writers to avoid metadata-lock timeouts.
- Back up the database before schema upgrades.
When it happens
Trigger: ensureWispDepSurrogateKey finds no `id` column and the ADD COLUMN ... PRIMARY KEY DDL fails — DEFAULT (UUID()) expression unsupported by the engine/version, duplicate implicit PK conflict, privilege denial, or lock timeout.
Common situations: Older MySQL/Dolt versions without functional DEFAULT expressions; repair run on a server that rejects expression defaults; DB user lacking ALTER/INSERT needed to backfill UUIDs; concurrent writers blocking the ALTER.
Related errors
- dropping the wisp_dependencies primary key for the 0058 repa
- adding the wisp_dependencies id primary key for the 0058 rep
- pre-repair for migration %s: %w
- dropping idx_wisp_dep_type_target for the 0058 repair: %w
- dropping %s for the 0058 repair: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/754fe6206d2dc99e.
Report an issue: GitHub.