{"record":{"id":"8bf2360ed3311c78","repo":"golang-migrate/migrate","slug":"database-is-dirty-8bf236","errorCode":null,"errorMessage":"database is dirty","messagePattern":"database is dirty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"database/sqlserver/sqlserver.go","lineNumber":31,"sourceCode":"\n\t\"github.com/Azure/go-autorest/autorest/adal\"\n\t\"github.com/golang-migrate/migrate/v4\"\n\t\"github.com/golang-migrate/migrate/v4/database\"\n\tmssql \"github.com/microsoft/go-mssqldb\" // mssql support\n)\n\nfunc init() {\n\tdatabase.Register(\"sqlserver\", &SQLServer{})\n}\n\n// DefaultMigrationsTable is the name of the migrations table in the database\nvar DefaultMigrationsTable = \"schema_migrations\"\n\nvar (\n\tErrNilConfig                 = fmt.Errorf(\"no config\")\n\tErrNoDatabaseName            = fmt.Errorf(\"no database name\")\n\tErrNoSchema                  = fmt.Errorf(\"no schema\")\n\tErrDatabaseDirty             = fmt.Errorf(\"database is dirty\")\n\tErrMultipleAuthOptionsPassed = fmt.Errorf(\"both password and useMsi=true were passed\")\n)\n\nvar lockErrorMap = map[int]string{\n\t-1:   \"The lock request timed out.\",\n\t-2:   \"The lock request was canceled.\",\n\t-3:   \"The lock request was chosen as a deadlock victim.\",\n\t-999: \"Parameter validation or other call error.\",\n}\n\n// Config for database\ntype Config struct {\n\tMigrationsTable string\n\tDatabaseName    string\n\tSchemaName      string\n}\n\n// SQL Server connection","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/database/sqlserver/sqlserver.go#L13-L49","documentation":"ErrDatabaseDirty signals the migrations table records a migration version with a dirty flag set, meaning a previous migration failed mid-execution (partially applied) and the schema state is unknown. The driver refuses further migrations until a human resolves the state.","triggerScenarios":"A prior migration panicked, the process crashed, or the connection dropped while a migration was applying, leaving dirty=true on the version row; retrying migrate.Up/Stef afterwards.","commonSituations":"Long DDL migrations interrupted by deploys or OOM kills; network partitions during migration; concurrent migration processes after a failed run.","solutions":["Inspect the schema_migrations table: check the version and dirty flag, and verify whether the failing migration's DDL actually applied","Manually fix the schema (complete or roll back the partial migration), then set dirty=false (or force the version)","Use migrate.Force(version) via CLI or driver to clear the dirty state once the database matches the recorded version, then re-run migrations","Prevent recurrence by running migrations in a transaction-backed driver or with a lock/single runner"],"exampleFix":"-- before (dirty state)\nSELECT * FROM schema_migrations; -- version 7, dirty 1\n-- after verifying migration 7 fully applied\nUPDATE schema_migrations SET dirty = 0 WHERE version = 7;","handlingStrategy":"validation","validationCode":"var version uint; var dirty bool\nrow := db.QueryRow(\"SELECT version, dirty FROM schema_migrations\")\nif err := row.Scan(&version, &dirty); err == nil && dirty {\n    return fmt.Errorf(\"database dirty at version %d; resolve manually before migrating\", version)\n}","typeGuard":null,"tryCatchPattern":"if errors.Is(err, sqlserver.ErrDatabaseDirty) {\n    // inspect schema_migrations, fix schema state, then:\n    // migrate.Force(knownGoodVersion) before retrying Up\n}","preventionTips":["Run migrations under the driver's Lock so only one process migrates at a time","Use transactional migration runs where the driver supports it","Alert on dirty=true rows in schema_migrations","Never force-clear dirty without verifying the actual schema state"],"tags":["go","sqlserver","database","migration","dirty-state","partial-migration"],"backgroundTag":"database-is-dirty","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}