The Migration Inconsistency Detected error means Django’s migration system thinks your database schema is out of sync with your project’s migration files, and it doesn’t know how to proceed safely. It’s usually triggered when migrations are applied or unapplied in an order that Django didn’t expect, or when the state of the django_migrations table in your database gets corrupted.

Here are the most common causes and how to fix them:

1. Manual Database Changes

Diagnosis: You or another process directly modified the database schema (e.g., using psql, mysql, or a GUI tool) without going through Django’s migration system.

Command:

python manage.py migrate --check

This command will report Migration X.Y.Z is already applied to partition X but is not in the database. or similar, indicating the mismatch.

Fix: If the manual change was intended and you want to align your project with the existing database:

  1. Identify the unapplied migration: Look at the output of migrate --check to see which migration Django thinks is missing from the database.
  2. Mark the migration as applied:
    python manage.py migrate --run-syncdb
    
    This command bypasses the actual migration logic and just updates the django_migrations table to reflect the current state of the database. Use with extreme caution.

Why it works: The django_migrations table is Django’s source of truth for applied migrations. This command manually updates that table to match what’s actually in the database, making Django think everything is okay.

2. Out-of-Order Migration Application

Diagnosis: Migrations were applied or unapplied in a non-sequential order, or a migration was skipped. This often happens in complex development workflows or when reverting to older states.

Command:

python manage.py migrate --check

This will likely show a dependency error, like Migration app.0001_initial depends on app.0000_initial but app.0000_initial is not installed.

Fix:

  1. Identify the problematic migrations: Examine the migrations/ directory in your apps and the django_migrations table in your database. Find the sequence where the order is broken.
  2. Re-sync to a known good state: If you have a clear "last known good" state, you can try to reset to that.
    • Option A: Unapply and reapply.
      python manage.py migrate <app_name> <previous_migration_name>
      python manage.py migrate <app_name>
      
      This unapplies all migrations after <previous_migration_name> for <app_name> and then reapplies them. You’ll need to carefully determine <previous_migration_name>.
    • Option B: Fake migrations. If you are certain the database schema matches a particular migration file, you can tell Django to "fake" apply it.
      python manage.py migrate <app_name> <migration_name> --fake
      
      Repeat for any other migrations that are out of sync but whose schema already exists in the database. Then run python manage.py migrate --check to verify.

Why it works: Faking a migration tells Django that the migration has been applied without actually running the SQL. This is useful when the database state already reflects the migration’s changes, but Django’s django_migrations table doesn’t. Reapplying migrations in the correct order ensures Django’s internal state aligns with the database.

3. Git Merge Conflicts in Migration Files

Diagnosis: During a Git merge, migration files were modified by multiple branches simultaneously, leading to conflicts that were resolved incorrectly or incompletely. This can corrupt the migration files themselves.

Command:

git status

Look for modified migration files. Then run:

python manage.py migrate --check

Fix:

  1. Inspect and resolve conflicts: Manually open the conflicted migration files (e.g., app/migrations/000X_auto_....py). The conflict markers (<<<<<<<, =======, >>>>>>>) will show where the divergence occurred.
  2. Recreate the migration: The safest approach is often to discard the conflicted migration(s) and generate a new one.
    • Backup: Copy the problematic migration file(s) elsewhere.
    • Delete: Remove the conflicted migration file(s) from your project.
    • Generate new:
      python manage.py makemigrations <app_name>
      
      This will create a new migration file that reflects the current state of your models.
    • Apply and fake if necessary:
      python manage.py migrate <app_name> <previous_migration_name> # Unapply the problematic one if it was partially applied
      python manage.py migrate <app_name> # Apply the new one
      
      If the new migration fails because the schema already exists, you might need to fake it: python manage.py migrate <app_name> <new_migration_name> --fake.

Why it works: By discarding corrupted files and regenerating a clean migration, you remove the syntax or logical errors introduced by the merge. Faking it allows Django to acknowledge the new migration’s existence without re-applying schema changes that are already present.

4. Database Schema Drift on Multiple Environments

Diagnosis: If you have multiple environments (dev, staging, production) and you’ve manually applied changes or used a different migration application order in one environment, it can lead to inconsistencies when you try to sync them.

Command:

python manage.py migrate --check

This will highlight differences between your project’s migration files and the django_migrations table in the database of the environment you’re connected to.

Fix:

  1. Identify the source of truth: Decide which environment has the most accurate and desired schema.
  2. Reset and reapply: For the inconsistent environment(s):
    • Backup your database.
    • Drop all tables: This is the most drastic but often the cleanest way to ensure consistency.
      # Example for PostgreSQL using psql
      psql -d your_db_name -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
      
      Adapt the command for your specific database.
    • Recreate and migrate:
      python manage.py migrate
      
      This will recreate all tables and apply all migrations from scratch.

Why it works: Dropping all tables and reapplying migrations from scratch ensures that the database schema exactly matches the state defined by your project’s migration files, starting from a clean slate.

5. Corrupted django_migrations Table

Diagnosis: In rare cases, the django_migrations table itself might have been corrupted, leading to incorrect entries or missing rows that confuse Django’s migration logic.

Command:

python manage.py migrate --check

This might yield very strange errors, or migrate --list might show a nonsensical state.

Fix:

  1. Inspect the django_migrations table:
    SELECT * FROM django_migrations;
    
    Look for duplicate entries for the same migration, NULL values where they shouldn’t be, or an illogical sequence.
  2. Manually correct the table:
    • If you know the correct state: You can directly DELETE or INSERT rows to make the table reflect your intended applied migrations.
    • If unsure, reset: The safest bet is to clear the table and re-run migrations.
      TRUNCATE TABLE django_migrations; -- Or DELETE FROM django_migrations;
      
      Then, run:
      python manage.py migrate
      
      This will re-apply all migrations. If this fails, you might need to python manage.py migrate --fake specific migrations that were already applied but not recorded correctly.

Why it works: By truncating or correcting the django_migrations table, you reset Django’s knowledge of applied migrations. The subsequent migrate command then rebuilds this knowledge correctly by applying all pending migrations.

6. Concurrent Migration Operations

Diagnosis: Multiple processes attempting to run migrations simultaneously on the same database can lead to race conditions and inconsistent states. This is particularly common in CI/CD pipelines or when multiple developers are working on the same branch and deploying.

Command:

python manage.py migrate --check

This might show errors related to tables not existing when they should, or vice-versa, depending on which process got ahead or fell behind.

Fix:

  1. Implement locking or sequential execution:
    • CI/CD: Ensure your CI pipeline runs migrations as a single, atomic step. Avoid separate steps for makemigrations and migrate if possible, or ensure the migrate step is locked.
    • Development: Establish a team convention to only run migrations one at a time.
  2. If already inconsistent: You’ll likely need to fall back to one of the methods above (e.g., migrate --check and then faking or reapplying) after ensuring only one process is running migrations.

Why it works: Preventing concurrent access to the migration process ensures that the django_migrations table and the database schema are updated in a predictable, sequential manner, avoiding race conditions.

After resolving the inconsistency, the next error you might encounter is a DatabaseError if your application code tries to access a model field that was added in a migration that hasn’t been applied yet, or if a constraint violation occurs due to the schema mismatch.

Want structured learning?

Take the full Django course →