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

  1. Check the wrapped cause: unsupported DEFAULT (UUID()) → upgrade Dolt/MySQL to a version supporting expression defaults.
  2. Re-run the guarded repair after fixing the engine/privilege issue.
  3. Grant ALTER (and privilege to evaluate UUID backfill) to the migration user.
  4. 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

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


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