{"record":{"id":"e1e516799a0a1ac6","repo":"gastownhall/beads","slug":"dropping-the-wisp-dependencies-primary-key-for-the","errorCode":null,"errorMessage":"dropping the wisp_dependencies primary key for the 0058 repair: %w","messagePattern":"dropping the wisp_dependencies primary key for the 0058 repair: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/wisp_dep_forward_repair.go","lineNumber":355,"sourceCode":"\t\tpresent, err := schemaConstraintExists(ctx, db, wispDepTable, c.name)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !present {\n\t\t\tcontinue\n\t\t}\n\t\tif _, err := db.ExecContext(ctx, \"ALTER TABLE wisp_dependencies DROP FOREIGN KEY \"+c.name); err != nil {\n\t\t\treturn fmt.Errorf(\"dropping %s for the 0058 repair: %w\", c.name, err)\n\t\t}\n\t}\n\n\thasPK, err := schemaHasPrimaryKey(ctx, db, wispDepTable)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif hasPK {\n\t\tif _, err := db.ExecContext(ctx, \"ALTER TABLE wisp_dependencies DROP PRIMARY KEY\"); err != nil {\n\t\t\treturn fmt.Errorf(\"dropping the wisp_dependencies primary key for the 0058 repair: %w\", err)\n\t\t}\n\t}\n\n\thasGenerated, err := schemaColumnExists(ctx, db, wispDepTable, \"depends_on_id\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tif hasGenerated {\n\t\tif _, err := db.ExecContext(ctx, \"ALTER TABLE wisp_dependencies DROP COLUMN depends_on_id\"); err != nil {\n\t\t\treturn fmt.Errorf(\"dropping wisp_dependencies.depends_on_id for the 0058 repair: %w\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// ensureWispDepSurrogateKey adds the final shape's id column and primary key.\n//\n// It is added BEFORE deduplication on purpose. The natural identity of a row","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/wisp_dep_forward_repair.go#L337-L373","documentation":"Wraps a failure when dropping the legacy primary key of wisp_dependencies (`ALTER TABLE wisp_dependencies DROP PRIMARY KEY`) during the 0058 repair. This is required before the final surrogate `id` key can take over. The DDL failed after schemaHasPrimaryKey confirmed a PK exists, aborting the repair.","triggerScenarios":"dropWispDepLegacyShape executes `ALTER TABLE wisp_dependencies DROP PRIMARY KEY` and it fails — the PK column is referenced by a foreign key from another table (MySQL refuses), insufficient privileges, lock contention, or Dolt engine restriction.","commonSituations":"Another table still holds a FK into the old PK column; repair run partially then resumed with leftover constraints; DB user lacking ALTER; long-running transactions blocking the metadata lock.","solutions":["Check the wrapped cause: if an FK references the PK, drop the dependent FK first or confirm the repair's earlier FK-drop steps ran.","Re-run the repair — steps are individually guarded so a partial pass resumes safely.","Grant the migration user ALTER privilege.","Ensure no other sessions hold open transactions on wisp_dependencies during the migration."],"exampleFix":"// before: DROP PRIMARY KEY fails — FK from child table still references old PK\n// after: resume full guarded repair so FK drops precede the PK drop\nif err := repairWispDependenciesForwardShape(ctx, db); err != nil {\n    return fmt.Errorf(\"resume repair after clearing dependent FKs: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// ensure no foreign keys (from any table) still reference wisp_dependencies' PK\nrows, err := db.QueryContext(ctx, `SELECT TABLE_NAME, CONSTRAINT_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME = 'wisp_dependencies'`)\nif err != nil { log.Fatalf(\"cannot check FK references: %v\", err) }\nfor rows.Next() {\n    var t, c string\n    _ = rows.Scan(&t, &c)\n    log.Printf(\"dependent FK: %s.%s — must be dropped before PK drop\", t, c)\n}\nrows.Close()","typeGuard":null,"tryCatchPattern":"if err := repairWispDependenciesForwardShape(ctx, db); err != nil {\n    if strings.Contains(err.Error(), \"dropping the wisp_dependencies primary key\") {\n        // a dependent FK likely remains; inspect and drop it, then re-run the guarded repair\n        return fmt.Errorf(\"clear dependent FKs before resuming: %w\", err)\n    }\n    return err\n}","preventionTips":["Never hand-run ALTERs piecemeal; always resume via the guarded repair.","Ensure child-table FKs are dropped in the same pass before the PK drop.","Block long-running transactions during migration to avoid metadata-lock waits.","Grant ALTER to the migration user."],"tags":["database","schema-repair","migration","primary-key","ddl"],"backgroundTag":"schema-migration-ddl-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}