BackendBench
Coffee

Home โ€บ Java exceptions โ€บ SQLIntegrityConstraintViolationException

Checked exception ยท java.sql

SQLIntegrityConstraintViolationException: causes and fixes

A SQL statement violated a database constraint: unique key, primary key, foreign key or NOT NULL.

What it looks like

java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'asha@example.com' for key 'users.uk_email'

Extends SQLNonTransientException in java.sql.

What it means

The database rejected a write because it would break a rule defined in the schema. The vendor message names the constraint, which is the most useful part: a duplicate key (unique or primary key), a foreign key that points at a missing row or is still referenced, or a NOT NULL column that received null. Drivers differ in the exact type thrown (PostgreSQL throws a generic PSQLException with SQLState 23505 for unique violations), but SQLState class 23 always means integrity constraint violation.

Common causes

How to fix it

  1. Read the constraint name in the message and map it back to the schema.
  2. For duplicates, check first and also handle the exception: the check alone has a race, the constraint is the real guarantee.
  3. Use upserts (INSERT ... ON CONFLICT, MERGE) where idempotency is intended.
  4. Delete children before parents or define ON DELETE CASCADE where the model calls for it.

Broken and fixed

fails
if (!repo.existsByEmail(email)) {
    repo.save(new User(email)); // two requests can both pass the check
}
works
try {
    repo.save(new User(email));
} catch (DataIntegrityViolationException e) {
    throw new EmailAlreadyUsedException(email);
}

๐Ÿ”Ž Unravel the failing code ๐Ÿ”Ž Unravel the fix

In Spring and enterprise code

Spring translates this into DataIntegrityViolationException (or DuplicateKeyException for unique violations), so you will usually catch the Spring type, not the java.sql one.

Debug it faster

Paste the whole stack trace into the stack trace beautifier to hide framework frames, jump to the root cause and find the first line of your own code. It runs in your browser, so the trace never leaves your machine.

Frequently asked questions

Is SQLIntegrityConstraintViolationException a checked or unchecked exception?

SQLIntegrityConstraintViolationException is a checked exception (it extends SQLNonTransientException), so the compiler forces you to catch it or declare it with throws.

Which package is SQLIntegrityConstraintViolationException in?

It lives in java.sql, so the import is import java.sql.SQLIntegrityConstraintViolationException;.

What is the first thing to check when I see SQLIntegrityConstraintViolationException?

Read the message and the first stack trace line in your own code. The usual causes are: Inserting a row whose unique or primary key value already exists, often because of a race between two requests; and Inserting a child row for a parent that does not exist, or deleting a parent that still has children.

Related exceptions

More tools you might need