Rohan Yeole - HomepageRohan Yeole

django.db.utils.ProgrammingError - Relation Already Exists

By Rohan Yeole
Table of Contents

When duplicate tables are created during migrations, Django shows django.db.utils.ProgrammingError - Relation Already Exists, blocking auto admin registration. 

This error usually pops up when Django tries to create a database table (via migrate) that already exists in your database, but not in Django’s migration history.
In short: Django thinks the table doesn't exist, but the database knows it does.
Example:
You created a model like this:

class Post(models.Model):
title = models.CharField(max_length=100)
Then ran:
python manage.py makemigrations
python manage.py migrate

Common Causes

Here’s when I usually see this:

  • You manually created tables in the DB (e.g., via PgAdmin or SQL).
  • You deleted migrations but didn’t drop the database tables.
  • You checked out a Git branch with old migrations and ran migrate.
  • Your model class changed, but the migration state got out of sync.
  • You ran migrate after copying a production DB without cleaning up.

Drop the Table (if you don’t need it)

If the table exists but has no important data yet:

PostgreSQL:

DROP TABLE blog_post; 
Or via Django shell:
python manage.py dbshell
Then re-run:
python manage.py migrate

Fake the Migration (if the table is already in sync)

If the table should exist but the migration just isn’t aware of it:

python manage.py migrate your_app_name --fake
This tells Django: “Don’t actually run SQL — just mark it as done.”

Reset Migrations (last resort)

If your migrations are a mess and you’re still in development:

find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc" -delete
Then:
python manage.py makemigrations
python manage.py migrate --fake
But be careful! Only do this if you’re sure no production data is at risk.

Pro Tip: Use showmigrations

If you want to see what migrations Django thinks are applied:

python manage.py showmigrations
This helps verify if your app's migration is registered properly.

Related Fixes and Resources

How to Prevent This in the Future

  • Don’t delete migrations manually unless you reset the DB.
  • Be cautious when switching branches with different migration states.
  • Use --fake wisely, and only when DB and models match.
  • If working in a team: sync migrations before committing new ones.

Final Thoughts

This error scared the heck out of me when I first saw it. But now I know: it’s just Django being cautious. 

Once you understand how migrations work, these issues become easy to fix — and even easier to avoid.

Have you faced a weird Django error? Drop me a line