On this page

Engineering7 min read

Fix Django IntegrityError: UNIQUE Constraint Failed -> 5 Causes and Fixes

Django IntegrityError means a database constraint was violated. Here are the 5 most common causes: duplicate records, missing migrations, race conditions, and the exact fix for each.

DjangoPythonIntegrityErrorPostgreSQLdebugging

What Is Django IntegrityError?

Django raises IntegrityError when a database operation violates a constraint: UNIQUE, NOT NULL, FOREIGN KEY, or CHECK. Django does not catch these automatically. They bubble up as unhandled exceptions unless you wrap the database call.

Error: django.db.utils.IntegrityError: UNIQUE constraint failed: auth_user.username

The error always includes the table name and column name after the colon. That is your starting point. Find which model maps to that table, find which field has the constraint, and trace back to where you are writing that field.

Cause 1: Duplicate Value on a UNIQUE Field

Most common cause. You are inserting or updating a record with a value that already exists on a field marked unique=True.

python
# models.py
class UserProfile(models.Model):
    username = models.CharField(max_length=100, unique=True)
    email = models.EmailField()

# Two users with the same username raises IntegrityError
UserProfile.objects.create(username="alice", email="a@example.com")
UserProfile.objects.create(username="alice", email="b@example.com")

Use get_or_create when you want "create if not exists", or update_or_create for upsert behavior:

python
profile, created = UserProfile.objects.get_or_create(
    username="alice",
    defaults={"email": "a@example.com"}
)

Cause 2: Missing or Unapplied Migration After Model Change

Adding unique=True to an existing field, or adding a new unique constraint, requires a migration. If you forget to run it, the database schema and your Django model disagree. Inserts that Django thinks are valid fail at the database level.

Error: django.db.utils.IntegrityError: UNIQUE constraint failed: myapp_product.sku

Check migration status first:

bash
python manage.py showmigrations myapp
python manage.py makemigrations
python manage.py migrate

If the constraint was added to an existing field with existing data, handle duplicates before migrating:

python
from django.db import migrations

def deduplicate_sku(apps, schema_editor):
    Product = apps.get_model('myapp', 'Product')
    seen = set()
    for product in Product.objects.order_by('created_at'):
        if product.sku in seen:
            product.sku = f"{product.sku}-{product.id}"
            product.save()
        seen.add(product.sku)

class Migration(migrations.Migration):
    dependencies = [('myapp', '0012_previous')]
    operations = [migrations.RunPython(deduplicate_sku)]

Cause 3: Race Condition on Concurrent Inserts

Two requests arrive at the same time. Both check whether the username exists, both get False, both try to insert. One succeeds. The other raises IntegrityError. The UNIQUE constraint is doing its job. The bug is the check-then-insert pattern.

python
# Check and insert are not atomic
def register_user(username, email):
    if not User.objects.filter(username=username).exists():
        User.objects.create(username=username, email=email)

Do not check first. Try the insert and catch IntegrityError:

python
from django.db import IntegrityError

def register_user(username, email):
    try:
        user = User.objects.create(username=username, email=email)
        return user, True
    except IntegrityError:
        user = User.objects.get(username=username)
        return user, False

Note: This pattern, try insert then catch and get, is safe under concurrent load. get_or_create does the same thing internally using atomic transactions depending on the database backend.

Cause 4: NOT NULL Constraint on a Field Without a Default

Adding a new required field to an existing model without providing a default fails when existing rows are migrated. Django prompts you during makemigrations, but if you bypass the prompt or script migrations manually, the NOT NULL violation hits at migration time.

Error: django.db.utils.IntegrityError: NOT NULL constraint failed: myapp_order.customer_id

Add the field as nullable first, then backfill, then remove the null:

python
class Migration(migrations.Migration):
    operations = [
        # Step 1: add nullable
        migrations.AddField(
            model_name='order',
            name='customer_id',
            field=models.IntegerField(null=True),
        ),
    ]

# In the next migration: backfill data, then add the NOT NULL constraint

Cause 5: FOREIGN KEY Violation

Inserting a row that references a non-existent parent record. Common when creating related objects out of order, or when the parent was deleted and on_delete was not set correctly.

Error: django.db.utils.IntegrityError: insert or update on table "myapp_order" violates foreign key constraint

python
# Order references customer_id=999 which does not exist
Order.objects.create(customer_id=999, total=49.99)

Validate the parent exists before creating the child:

python
from django.shortcuts import get_object_or_404

def create_order(request, customer_id):
    customer = get_object_or_404(Customer, id=customer_id)
    order = Order.objects.create(customer=customer, total=49.99)
    return order

How to Catch IntegrityError Gracefully

In views and API handlers, wrap database operations to return a useful error instead of a 500:

python
from django.db import IntegrityError
from django.http import JsonResponse

def create_user_view(request):
    try:
        user = User.objects.create(
            username=request.POST['username'],
            email=request.POST['email']
        )
        return JsonResponse({"id": user.id}, status=201)
    except IntegrityError as e:
        return JsonResponse({"error": "Username already taken"}, status=409)

Quick Reference

IntegrityError typeCauseFix
UNIQUE constraint failedDuplicate value on unique fieldget_or_create or catch and return existing
NOT NULL constraint failedField missing value, no defaultAdd default or use nullable migration
Foreign key violationParent record does not existValidate parent ID before insert
Check constraint violationValue outside allowed rangeValidate at model level before saving

For race condition bugs specifically, IntegrityError that appears under load but not locally, paste the view and model into DebugAI. It identifies check-then-insert patterns and suggests the atomic equivalent.

Debug faster starting today.

Free VS Code extension. 10 sessions/day. No credit card.

Install Free →

Related Posts

Engineering

GitHub Copilot Just Changed Its Pricing. What Developers Need to Know

5 min read

Engineering

Why Your AI Agent Harness Fails at Debugging (And How to Fix It)

5 min read

← All posts