How to fix SQLITE_CONSTRAINT_UNIQUE: UNIQUE constraint failed in SQLite
This error occurs when you attempt to insert or update a row with a value that already exists in a column marked as UNIQUE. SQLite enforces uniqueness constraints and rejects duplicate values, preventing data inconsistency in your database.
Quick fix
Fixes SQLITE_CONSTRAINT_UNIQUE
-- Check if a record with this email already exists
SELECT COUNT(*) FROM users WHERE email = 'john@example.com';
-- If count is 0, safe to insert
IF count = 0 THEN
INSERT INTO users (id, email, name) VALUES (1, 'john@example.com', 'John');
END IF;- Check if the record already exists before inserting
- Use INSERT OR REPLACE to overwrite existing records
- Use INSERT OR IGNORE to skip duplicates
- Use AUTOINCREMENT for primary keys to avoid manual conflicts
-- Check if a record with this email already existsSELECT COUNT(*) FROM users WHERE email = 'john@example.com';-- If count is 0, safe to insertIF count = 0 THENINSERT INTO users (id, email, name) VALUES (1, 'john@example.com', 'John');END IF;SQLITE_CONSTRAINT_UNIQUE: UNIQUE constraint failed
What this error means
The SQLITE_CONSTRAINT_UNIQUE error indicates that your SQL query violates a UNIQUE constraint on one or more columns in your table. A UNIQUE constraint ensures that all values in a column (or combination of columns) are distinct—no two rows can have the same value for that column. When you attempt to INSERT or UPDATE a record with a value that already exists in a uniquely-constrained column, SQLite aborts the operation and raises this constraint violation error. The operation fails completely, and no changes are committed to the database unless you explicitly use a conflict resolution clause.
Typical symptoms
- INSERT or UPDATE queries fail with "UNIQUE constraint failed" message
- Application crashes or throws an exception when trying to save duplicate data
- Duplicate key appears to be allowed, but database rejects the insert silently
- Data integrity issues when syncing or importing data from other sources
- Multiple NULL values in a UNIQUE column cause confusion (SQLite treats all NULLs as distinct)
Common causes
- Attempting to insert a row with an id or unique field value that already exists in the table
- Forgetting to check if a record exists before inserting or updating
- Not using auto-increment (AUTOINCREMENT or GENERATED ALWAYS AS IDENTITY) for primary keys, leading to manual id conflicts
- Importing or syncing data without deduplicating or checking for existing records first
- Multiple business processes inserting the same unique value concurrently without proper locking or transaction isolation
- Column was defined with UNIQUE constraint but application code does not account for this restriction
How to fix "SQLITE_CONSTRAINT_UNIQUE: UNIQUE constraint failed"
Before performing an INSERT, query the table to verify that the unique value does not already exist:
-- Check if a record with this email already exists
SELECT COUNT(*) FROM users WHERE email = 'john@example.com';
-- If count is 0, safe to insert
IF count = 0 THEN
INSERT INTO users (id, email, name) VALUES (1, 'john@example.com', 'John');
END IF;In Python with sqlite3:
import sqlite3
connection = sqlite3.connect('database.db')
cursor = connection.cursor()
# Check if email exists
cursor.execute('SELECT COUNT(*) FROM users WHERE email = ?', ('john@example.com',))
if cursor.fetchone()[0] == 0:
cursor.execute('INSERT INTO users (id, email, name) VALUES (?, ?, ?)',
(1, 'john@example.com', 'John'))
connection.commit()If you want to update an existing record when a duplicate is encountered, use the REPLACE conflict resolution algorithm. This removes the old row and inserts the new one:
-- Will replace any existing user with email 'john@example.com'
REPLACE INTO users (id, email, name) VALUES (1, 'john@example.com', 'John Smith');Or use the ON CONFLICT clause (modern SQLite 3.24.0+):
INSERT INTO users (id, email, name) VALUES (1, 'john@example.com', 'John')
ON CONFLICT(email) DO UPDATE SET name = 'John';In Python:
cursor.execute('''
INSERT INTO users (id, email, name) VALUES (?, ?, ?)
ON CONFLICT(email) DO UPDATE SET name = 'John'
''', (1, 'john@example.com', 'John'))
connection.commit()If you want to silently skip inserting a duplicate record (without raising an error), use the IGNORE conflict resolution algorithm:
-- Will skip this insert if email already exists, no error raised
INSERT OR IGNORE INTO users (id, email, name) VALUES (1, 'john@example.com', 'John');This is useful when batch-inserting data and you want to skip duplicates without stopping the entire operation.
cursor.execute('''
INSERT OR IGNORE INTO users (id, email, name) VALUES (?, ?, ?)
''', (1, 'john@example.com', 'John'))
connection.commit()Instead of manually assigning id values, let SQLite auto-generate unique primary keys using AUTOINCREMENT:
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL
);
-- Don't specify id, let SQLite generate it
INSERT INTO users (email, name) VALUES ('john@example.com', 'John');
INSERT INTO users (email, name) VALUES ('jane@example.com', 'Jane');In Python:
cursor.execute('''
INSERT INTO users (email, name) VALUES (?, ?)
''', ('john@example.com', 'John'))
connection.commit()Each insert automatically gets a unique id, eliminating id conflicts.
Wrap your INSERT/UPDATE operations in a try-except block to gracefully handle duplicates:
import sqlite3
connection = sqlite3.connect('database.db')
cursor = connection.cursor()
try:
cursor.execute('''
INSERT INTO users (id, email, name) VALUES (?, ?, ?)
''', (1, 'john@example.com', 'John'))
connection.commit()
print('User inserted successfully')
except sqlite3.IntegrityError as e:
if 'UNIQUE constraint failed' in str(e):
print('This email already exists. Updating instead...')
cursor.execute('''
UPDATE users SET name = ? WHERE email = ?
''', ('John', 'john@example.com'))
connection.commit()
else:
raiseIn JavaScript (Node.js with better-sqlite3):
const Database = require('better-sqlite3');
const db = new Database('database.db');
try {
const stmt = db.prepare('INSERT INTO users (id, email, name) VALUES (?, ?, ?)');
stmt.run(1, 'john@example.com', 'John');
} catch (error) {
if (error.message.includes('UNIQUE constraint failed')) {
console.log('Email already exists. Updating instead...');
const updateStmt = db.prepare('UPDATE users SET name = ? WHERE email = ?');
updateStmt.run('John', 'john@example.com');
} else {
throw error;
}
}Advanced notes
NULL values are treated as distinct: SQLite has a special behavior where NULL values are considered different from each other. This means a UNIQUE column can contain multiple NULL values without violating the constraint. If this is not the desired behavior, add a NOT NULL constraint.
Compound unique constraints: You can define a UNIQUE constraint across multiple columns, ensuring that combinations of values are unique:
CREATE TABLE user_profiles (
user_id INTEGER,
platform TEXT,
username TEXT,
UNIQUE(user_id, platform)
);
-- OK: Same user on different platforms
INSERT INTO user_profiles VALUES (1, 'twitter', '@john');
INSERT INTO user_profiles VALUES (1, 'github', 'john123');
-- UNIQUE constraint failed: Duplicate user_id + platform combo
INSERT INTO user_profiles VALUES (1, 'twitter', '@john_dev');Conflict resolution algorithms: SQLite supports five conflict resolution modes: ROLLBACK (default), ABORT (default for INSERT/UPDATE), FAIL, IGNORE, and REPLACE. You can specify these at the table level when creating the table, or at the statement level when executing INSERT/UPDATE/DELETE operations.
UPSERT (INSERT ... ON CONFLICT): Modern SQLite (3.24.0+) supports UPSERT syntax for atomic insert-or-update operations:
INSERT INTO users (id, email, name) VALUES (1, 'john@example.com', 'John')
ON CONFLICT(id) DO UPDATE SET name = 'John';Frequently asked questions
- What does "SQLITE_CONSTRAINT_UNIQUE" mean?
- The SQLITE_CONSTRAINT_UNIQUE error indicates that your SQL query violates a UNIQUE constraint on one or more columns in your table. A UNIQUE constraint ensures that all values in a column (or combination of columns) are distinct—no two rows can have the same value for that column. When you attempt to INSERT or UPDATE a record with a value that already exists in a uniquely-constrained column, SQLite aborts the operation and raises this constraint violation error.
- How do I fix "SQLITE_CONSTRAINT_UNIQUE"?
- This error occurs when you attempt to insert or update a row with a value that already exists in a column marked as UNIQUE. SQLite enforces uniqueness constraints and rejects duplicate values, preventing data inconsistency in your database.
- What causes "SQLITE_CONSTRAINT_UNIQUE"?
- Attempting to insert a row with an id or unique field value that already exists in the table Forgetting to check if a record exists before inserting or updating Not using auto-increment (AUTOINCREMENT or GENERATED ALWAYS AS IDENTITY) for primary keys, leading to manual id conflicts
- Is the "SQLITE_CONSTRAINT_UNIQUE" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚SQLite Official Documentation
- 🔗
- 📖sqlite.org - conflict(Official Docs)
- 🔗
- 🔗
- 🐙github.com - 2613(GitHub)