Skip to content
Latchkey

Django "table already exists" - When to Use migrate --fake

Django tried to create a table that already exists because django_migrations does not record the migration as applied. The schema and the migration ledger disagree - --fake/--fake-initial records history without re-running SQL, but only when the schema truly matches.

What this error means

python manage.py migrate fails creating a table/column that already exists. It happens when a database already has the schema (adopted or pre-seeded) but Django’s migration table is empty or behind.

Django output
django.db.utils.ProgrammingError: relation "orders" already exists

(running 0001_initial against a database that already has the table)

Common causes

Schema exists but django_migrations is empty/behind

The database already has the tables (from another tool, a restored dump, or a prior run) while Django’s ledger does not record the migrations, so it re-runs the create.

Initial migration run against a pre-existing schema

Adopting an existing database with Django for the first time runs 0001_initial, which collides with the already-present tables.

How to fix it

Fake the initial migration when adopting a schema

When the existing schema matches the initial migration, record it as applied without running DDL.

Terminal
python manage.py migrate --fake-initial

Fake a specific migration to align history

If a specific migration’s changes are already present, mark just that one as applied.

Terminal
python manage.py migrate orders 0001 --fake

Prefer a clean database in CI

  1. In CI, start from an empty database so migrate applies the full history with no fakes.
  2. Reserve --fake/--fake-initial for adopting a genuinely pre-existing database.
  3. Verify the real schema matches before faking anything.

How to prevent it

  • Use empty databases in CI so no faking is needed.
  • Keep django_migrations consistent with the real schema.
  • Reserve --fake-initial for first-time adoption of an existing database.

Frequently asked questions

What causes ""table ... already exists" (Django)"?
The database already has the tables (from another tool, a restored dump, or a prior run) while Django’s ledger does not record the migrations, so it re-runs the create.
How do I fix "table ... already exists" (Django)?
When the existing schema matches the initial migration, record it as applied without running DDL.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card