Synthetic Industry

Troubleshooting guide · updated 2026-10-10

Django migration failed: inspect the database before rolling code back

Separate recorded migration status, actual schema changes and backend transaction support before retrying a partly applied deployment.

Preserve the failed operation

An app owner sees a release fail on a schema change and considers deploying the old code again. Retain the migration identifier, database backend and first redacted error. Have the authorised operator compare recorded migration state with the actual schema. showmigrations and sqlmigrate help inspect the plan; they are not permission to run a production change, and generated SQL can reveal private schema details.

  • Keep the last known restore point and application revision.
  • Do not delete a migration file or mark it applied just to hide the error.

Recovery depends on the backend and operation

Django 5.2 documents a default transaction for migrations on PostgreSQL and SQLite. MySQL schema changes are not protected by a migration-wide DDL transaction, so earlier operations can remain after a failure. Even on a transactional backend, inspect whether this migration sets atomic=False or contains other effects outside the database. An unapplied status does not by itself prove that no schema operation occurred.

  • Separate earlier successfully applied migrations from the specific failed migration.
  • Do not blindly retry an already-created table or partly changed column.

A reverse operation is not data recovery

Reversing to an earlier migration depends on reversible operations. RunPython without a reverse callable, or other irreversible work, can prevent reversal. Reverting code does not restore deleted data. For data migrations, inspect historical model use through apps.get_model; importing today's model can make an old migration fail when replayed on a fresh database.

  • Rehearse the chosen forward repair or supported reversal on an isolated copy.
  • Keep backups and any recovered data on the approved operator-held route, not in an enquiry or public repository.

Acceptance requires consistent state and business checks

The recovery handover should name the actual schema state, applied migration state, chosen repair and remaining irreversible limits. On the agreed test copy, demonstrate the intended migration sequence and critical read/write flows. Production repair needs explicit authority and a tested recovery plan; this guide does not promise automatic rollback, zero loss or a fixed recovery time. Ask for a scoped migration or repair assessment with redacted context only.

Sources and limits

  • Django 5.2: migrations and backend support Checked 2026-10-10.
    • Django describes migrations as transactional by default on PostgreSQL and SQLite, but not MySQL schema changes.
    • Failed MySQL migrations may need manual repair of completed schema operations before retry.
    • atomic=False disables the migration-wide transaction; irreversible operations cannot necessarily be undone with migrate.
    • Data migrations should use historical models from apps.get_model rather than importing current model classes.