{"record":{"id":"f6a20b1afb0ca9f6","repo":"ory/hydra","slug":"problem-deleting-migration-version-s-your-databa","errorCode":null,"errorMessage":"problem deleting migration version %s. YOUR DATABASE MAY BE IN AN INCONSISTENT STATE! MANUAL INTERVENTION REQUIRED!","messagePattern":"problem deleting migration version (.+?)\\. YOUR DATABASE MAY BE IN AN INCONSISTENT STATE! MANUAL INTERVENTION REQUIRED!","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"oryx/popx/migrator.go","lineNumber":401,"sourceCode":"\t\t\t\t\treturn errors.Errorf(\"neither normal (%s) nor legacy migration (%s) exist\", mi.Version, legacyVersion)\n\t\t\t\t}\n\t\t\t} else if !exists {\n\t\t\t\treturn errors.Errorf(\"migration version %s does not exist\", mi.Version)\n\t\t\t}\n\n\t\t\tif err := mi.Valid(); err != nil {\n\t\t\t\treturn errors.WithStack(err)\n\t\t\t}\n\n\t\t\tif mb.shouldNotUseTransaction(mi) {\n\t\t\t\terr := mi.Runner(mi, c)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn errors.WithStack(err)\n\t\t\t\t}\n\n\t\t\t\t// #nosec G201 - mtn is a system-wide const\n\t\t\t\tif err := c.RawQuery(fmt.Sprintf(\"DELETE FROM %s WHERE version = ?\", mtn), mi.Version).Exec(); err != nil {\n\t\t\t\t\treturn errors.Wrapf(err, \"problem deleting migration version %s. YOUR DATABASE MAY BE IN AN INCONSISTENT STATE! MANUAL INTERVENTION REQUIRED!\", mi.Version)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif err := mb.isolatedTransaction(ctx, \"down\", func(conn *pop.Connection) error {\n\t\t\t\t\terr := mi.Runner(mi, conn)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.WithStack(err)\n\t\t\t\t\t}\n\n\t\t\t\t\t// #nosec G201 - mtn is a system-wide const\n\t\t\t\t\tif err := conn.RawQuery(fmt.Sprintf(\"DELETE FROM %s WHERE version = ?\", mtn), mi.Version).Exec(); err != nil {\n\t\t\t\t\t\treturn errors.Wrapf(err, \"problem deleting migration version %s\", mi.Version)\n\t\t\t\t\t}\n\n\t\t\t\t\treturn nil\n\t\t\t\t}); err != nil {\n\t\t\t\t\treturn errors.WithStack(err)\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/popx/migrator.go#L383-L419","documentation":"When a Down migration runs outside a transaction (no-transaction migration), the rollback schema change executes first; if the subsequent DELETE of the version row from schema_migration fails, the schema has been rolled back but the tracking row remains, leaving the database in an inconsistent state that requires manual intervention. The library cannot undo the applied rollback automatically.","triggerScenarios":"Calling Down for a no-transaction migration where the migration body succeeds but the DELETE FROM schema_migration fails (connection drop, lock, permissions).","commonSituations":"MySQL-style non-transactional DDL rollbacks followed by connection loss; concurrent lock on schema_migration; DB user lacking DELETE privileges; disk-full incidents.","solutions":["Verify the migration's rollback actually took effect in the schema","If the schema was rolled back, manually DELETE the version row: DELETE FROM schema_migration WHERE version='<version>';","If the rollback did not apply, fix the cause and manually remove or keep the row to match reality, then re-run Down","Use transactional migrations where the dialect supports transactional DDL"],"exampleFix":"// after a failed auto-delete, reconcile manually\n// SELECT 1 FROM schema_migration WHERE version='20221012101010';\n// DELETE FROM schema_migration WHERE version='20221012101010'; -- if rollback applied","handlingStrategy":"try-catch","validationCode":"// check DELETE privileges on the tracking table before no-tx rollbacks\nif err := db.RawQuery(\"SELECT 1 FROM schema_migration LIMIT 1\").Exec(); err != nil {\n    return fmt.Errorf(\"cannot read schema_migration; aborting no-tx Down: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := box.Down(ctx, 1); err != nil {\n    if strings.Contains(err.Error(), \"MANUAL INTERVENTION REQUIRED\") {\n        // verify whether the schema rollback applied; DELETE the version row manually if it did\n    }\n    return err\n}","preventionTips":["Prefer transactional migrations over NO-TX on DDL-transactional dialects","Grant DELETE on schema_migration to the migration user","Snapshot the database before running Down","Avoid concurrent lock holders on the tracking table during rollbacks"],"tags":["database","migration","data-consistency","go"],"backgroundTag":"inconsistent-migration-state","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}