MySQL error 1062 (Duplicate Entry) explained: what it means, why it happens, and how to fix it — with copy-paste code examples.
Read the full message: it names the duplicate value and the key ('Duplicate entry X for key Y'). If that does not apply, for idempotent inserts use `INSERT ... ON DUPLICATE KEY UPDATE col=VALUES(col)` or `INSERT IGNORE` — the full checklist is below.
MySQL Error Code: 1062
Official name: Duplicate Entry
System name: Duplicate entry
Service: MySQL
Duplicate entry '%s' for key %s
You may see this error reported as one of the following messages:
Duplicate entry 'a@b.com' for key 'users.email'Integrity constraint violation: 1062 Duplicate entry '1' for key 'primary'#1062 - Duplicate entry 'a@b.com' for key 'users.email'A users table has UNIQUE KEY users_email (email). A retry loop re-sends a signup after a network timeout — the first INSERT already succeeded. MySQL returns ERROR 1062 (23000): Duplicate entry 'john@example.com' for key 'users.email'. The key name in the message tells you exactly which unique index fired; PRIMARY fires the same way when a row with that id already exists.
Run these to confirm the cause before applying a fix — each command answers a specific question.
SHOW CREATE TABLE users;
The UNIQUE KEY / PRIMARY KEY lines list every index that can raise 1062 — match the key name from the error message.
SELECT email, COUNT(*) c FROM users
GROUP BY email HAVING c > 1;
Existing duplicates mean the unique index was added later (or is being added); clean them before the constraint can hold.
Is the duplicate insert intentional (retry / upsert)?
├─ YES → INSERT ... ON DUPLICATE KEY UPDATE name = VALUES(name)
│ or INSERT IGNORE when you only need 'already there' semantics
└─ NO → find the conflicting row
├─ row is valid → reject/fix the application input ('email taken')
└─ row is stale → delete or merge, then retry
Duplicate on AUTO_INCREMENT id?
└─ explicit id insert bypassed the counter →
bump it: ALTER TABLE users AUTO_INCREMENT = <MAX(id)+1>;
INSERT INTO users (email, name)
VALUES ('ada@example.com', 'Ada')
ON DUPLICATE KEY UPDATE
name = VALUES(name);
When the unique key already exists, the UPDATE branch runs instead of failing with 1062.
SELECT email, COUNT(*)
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
Locates existing rows that share a unique value so you can clean them before retrying.
Catch the driver error, check err.code === 'ER_DUP_ENTRY', and map it to HTTP 409 with the duplicate key name.
try {
await pool.query(
'INSERT INTO users (email) VALUES (?) ON DUPLICATE KEY UPDATE email = email',
[email],
)
} catch (err) {
if (err.code === 'ER_DUP_ENTRY') return res.status(409).json({ error: 'Email already taken' })
throw err
}
Let IntegrityError propagate to a handler that inspects the underlying driver code 1062.
from sqlalchemy.exc import IntegrityError
try:
session.add(user)
session.commit()
except IntegrityError as e:
if e.orig.args[0] == 1062:
raise DuplicateUser(email) from e
raise
Check errorInfo[1] === 1062 after catching PDOException and return 409.
try {
$pdo->exec("INSERT INTO users (email) VALUES ('$email')");
} catch (PDOException $e) {
if ($e->errorInfo[1] === 1062) { http_response_code(409); exit('email exists'); }
throw $e;
}
Most often this happens when inserting or updating a row whose value collides with an existing unique key (email, username, order number, external id), or when retrying an insert after a timeout or partial failure, so the row was actually created but the retry hits the unique index.
Read the full message: it names the duplicate value and the key ('Duplicate entry X for key Y').
This page documents fixes for: nodejs-mysql2, python-sqlalchemy, php-pdo.
Recommendations are editorial — DB Error Reference takes no payment or affiliate fees for tool listings.
This page is based on the official MySQL documentation linked below and adds practical troubleshooting guidance on top.