Fixing PG::UniqueViolation when there isn't a unique violation

Have you ever encountered a PG::UniqueViolation error when you’re certain there’s no duplicate data? The culprit is often a PostgreSQL sequence that’s out of sync.

The Problem

You see an error like:

PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "users_pkey"
DETAIL: Key (id)=(42) already exists.

But when you check, there’s no record with ID 42. What’s happening?

The Cause

PostgreSQL uses sequences to generate auto-incrementing IDs. Sometimes, especially after data imports or manual inserts, the sequence gets out of sync with the actual maximum ID in the table.

The Fix

Reset the sequence to the correct value:

SELECT setval('users_id_seq', (SELECT MAX(id) FROM users));

Or in Rails:

ActiveRecord::Base.connection.execute(
  "SELECT setval('users_id_seq', (SELECT MAX(id) FROM users))"
)

For All Tables

To fix all sequences at once:

ActiveRecord::Base.connection.tables.each do |table|
  ActiveRecord::Base.connection.reset_pk_sequence!(table)
end

Prevention

This issue commonly occurs after:

  • Data migrations or imports
  • Manual SQL inserts with explicit IDs
  • Restoring from backups

Always reset sequences after bulk data operations to avoid these mysterious errors.