PostgreSQL error 42P07 (Duplicate Table) explained: what it means, why it happens, and how to fix it — with copy-paste code examples.
Use CREATE TABLE IF NOT EXISTS for idempotent scripts. If that does not apply, check existence first with SELECT to_regclass('public.users') — the full checklist is below.
SQLSTATE: 42P07
Official name: Duplicate Table
System name: duplicate_table
Service: PostgreSQL
The statement attempted to create a table, view, or index whose name already exists in the target schema.
You may see this error reported as one of the following messages:
relation "users" already existsCREATE TABLE IF NOT EXISTS users (
id bigserial PRIMARY KEY,
email text UNIQUE NOT NULL
);
IF NOT EXISTS turns a would-be 42P07 into a no-op when the relation already exists.
SELECT to_regclass('public.users') IS NULL AS missing;
to_regclass returns NULL when the relation does not exist, letting scripts branch safely.
Pass checkfirst=True to create_all() so existing tables are skipped instead of raising 42P07.
Base.metadata.create_all(engine, checkfirst=True)
If the table exists but Django's migration history does not, mark the migration applied with --fake instead of re-creating the table.
python manage.py migrate myapp 0001 --fake
Use prisma migrate deploy in CI/CD; it only applies unapplied migrations and never re-creates existing tables.
npx prisma migrate deploy
Most often this happens when running a setup script twice without IF NOT EXISTS, or when re-running migrations against a database that already contains the tables.
Use CREATE TABLE IF NOT EXISTS for idempotent scripts.
This page documents fixes for: sqlalchemy, django, prisma.
Recommendations are editorial — DB Error Reference takes no payment or affiliate fees for tool listings.
This page is based on the official PostgreSQL documentation linked below and adds practical troubleshooting guidance on top.