{"record":{"id":"015f47f69186d04b","repo":"gastownhall/beads","slug":"dropping-dependencies-existing-primary-key-for-mi","errorCode":null,"errorMessage":"dropping dependencies' existing primary key for migration 0053: %w","messagePattern":"dropping dependencies' existing primary key for migration 0053: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/migration_repairs.go","lineNumber":549,"sourceCode":"\t\treturn nil\n\t}\n\n\tif _, err := db.ExecContext(ctx, \"ALTER TABLE dependencies MODIFY COLUMN id CHAR(36) NOT NULL\"); err != nil {\n\t\treturn fmt.Errorf(\"finalizing dependencies.id for migration 0053: %w\", err)\n\t}\n\n\thasAnyPrimaryKey, err := schemaHasPrimaryKey(ctx, db, \"dependencies\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"checking dependencies for an existing primary key: %w\", err)\n\t}\n\tif hasAnyPrimaryKey {\n\t\t// The #4690 drifted shape has dependencies keyed some other way (or\n\t\t// keyless): a table can carry only one PRIMARY KEY, so whatever is\n\t\t// there must go before id can become it. The uk_dep_* natural-identity\n\t\t// unique keys (0043) enforce the real uniqueness independently of\n\t\t// whatever this was, so dropping it is safe.\n\t\tif _, err := db.ExecContext(ctx, \"ALTER TABLE dependencies DROP PRIMARY KEY\"); err != nil {\n\t\t\treturn fmt.Errorf(\"dropping dependencies' existing primary key for migration 0053: %w\", err)\n\t\t}\n\t}\n\tif _, err := db.ExecContext(ctx, \"ALTER TABLE dependencies ADD PRIMARY KEY (id)\"); err != nil {\n\t\treturn fmt.Errorf(\"keying dependencies.id for migration 0053: %w\", err)\n\t}\n\treturn nil\n}\n\n// firstNonNullString returns the first valid (non-NULL) value among cols, or\n// \"\" if all are NULL.\nfunc firstNonNullString(cols ...sql.NullString) string {\n\tfor _, c := range cols {\n\t\tif c.Valid {\n\t\t\treturn c.String\n\t\t}\n\t}\n\treturn \"\"\n}","sourceCodeStart":531,"sourceCodeEnd":567,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/migration_repairs.go#L531-L567","documentation":"Wraps failure of `ALTER TABLE dependencies DROP PRIMARY KEY`. The drifted #4690 shape may key dependencies by some other column; because a table has only one PRIMARY KEY, the existing one must be removed before id can become it (uk_dep_* unique keys from 0043 already enforce real uniqueness).","triggerScenarios":"The table has a non-id PRIMARY KEY and `ALTER TABLE dependencies DROP PRIMARY KEY` fails: table locked by a concurrent writer, foreign keys referencing the current PK (some engines refuse), insufficient privileges (ALTER/INDEX), or Dolt rejecting the operation mid-repair.","commonSituations":"Another bd or SQL session open during upgrade; database user missing ALTER privilege; schema drift from out-of-band Dolt SQL edits that added referencing foreign keys.","solutions":["Close all other connections to the database and rerun `bd`","Confirm the account has ALTER/INDEX privileges: GRANT ALTER, INDEX ON beads.* TO ...","Check for foreign keys referencing the old PK and drop/recreate them around the repair","Inspect the wrapped %w error for the server-side reason (lock, FK, privilege) and address it"],"exampleFix":"// before: missing ALTER privilege\nGRANT ALTER, INDEX ON beads.* TO 'beads'@'localhost';\n// after: rerun migration\nbd ready","handlingStrategy":"validation","validationCode":"-- confirm no foreign keys reference the current PK before upgrading\nSELECT TABLE_NAME, CONSTRAINT_NAME\nFROM information_schema.KEY_COLUMN_USAGE\nWHERE REFERENCED_TABLE_NAME = 'dependencies';\n-- confirm ALTER privilege\nSHOW GRANTS FOR CURRENT_USER();","typeGuard":null,"tryCatchPattern":"if err := ensureSchema(ctx, db); err != nil {\n    if strings.Contains(err.Error(), \"dropping dependencies' existing primary key\") {\n        if strings.Contains(err.Error(), \"denied\") { /* grant ALTER/INDEX */ }\n        if strings.Contains(err.Error(), \"foreign key\") { /* drop/recreate FKs */ }\n        return retryAfterRemediation(err)\n    }\n    return err\n}","preventionTips":["Never hand-edit beads schema with out-of-band ALTERs","Use an account with ALTER/INDEX for upgrades","Close all SQL sessions against the db before migrating","Avoid adding FKs that reference beads-internal keys"],"tags":["database","migration","alter-table","primary-key"],"backgroundTag":"migration-backfill-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}