Troubleshooting
Magento 2 'Integrity Constraint Violation' Errors: Causes and Fixes
SQLSTATE[23000]: Integrity constraint violation covers two genuinely different problems that both throw the same error code — a duplicate entry (1062) and a foreign key violation (1452). Reading the exact message tells you which one you're dealing with.
Error 1452: Foreign Key Violation
This means a row is trying to reference a parent row that doesn't exist — most often seen during imports, partial data migrations, or a custom module that deletes parent records without cleaning up children first.
Find the exact table and constraint from the error message, then check SHOW CREATE TABLE to see what it actually requires:
SHOW CREATE TABLE catalog_product_entity_int;To find the actual orphaned rows for an EAV attribute table:
SELECT cpei.entity_id
FROM catalog_product_entity_int cpei
LEFT JOIN catalog_product_entity cpe ON cpe.entity_id = cpei.entity_id
WHERE cpe.entity_id IS NULL;Once you've confirmed which rows are orphaned, delete them directly rather than guessing at a broader fix:
DELETE cpei FROM catalog_product_entity_int cpei
LEFT JOIN catalog_product_entity cpe ON cpe.entity_id = cpei.entity_id
WHERE cpe.entity_id IS NULL;Error 1062: Duplicate Entry
This means something is trying to insert a value into a column with a unique constraint — SKU, URL key, or a custom unique attribute — that already exists.
Find the duplicates before touching anything:
SELECT sku, COUNT(*) as total
FROM catalog_product_entity
GROUP BY sku
HAVING total > 1;For duplicate URL keys specifically (a very common one after a bulk import):
SELECT value, COUNT(*) as total
FROM catalog_product_entity_varchar
WHERE attribute_id = (
SELECT attribute_id FROM eav_attribute WHERE attribute_code = 'url_key'
)
GROUP BY value
HAVING total > 1;Don't Reach for FOREIGN_KEY_CHECKS=0 First
It's tempting to disable constraint checking to make the error go away:
SET FOREIGN_KEY_CHECKS=0;This suppresses the symptom, not the problem — the orphaned or duplicate data is still there, and disabling checks in production risks making the inconsistency worse, not better. It's only reasonable as a temporary measure during a controlled, one-time import where you'll immediately clean up afterward and re-enable checks:
SET FOREIGN_KEY_CHECKS=0;
-- your import
SET FOREIGN_KEY_CHECKS=1;Where These Usually Come From
- A partial or interrupted data import (process died halfway through, leaving parent rows without their expected children or vice versa).
- A custom module deleting entities directly via SQL instead of through Magento's resource models, skipping the cleanup Magento normally handles for you.
- Restoring a database backup that's out of sync with the codebase's expected schema state.
General Approach
- Read the exact SQLSTATE message — is it 1452 (foreign key) or 1062 (duplicate)?
- Identify the exact table and constraint via
SHOW CREATE TABLE. - Query for the actual bad rows before deleting or modifying anything.
- Fix the data, not the constraint — the constraint exists because the data model requires it.
- Re-run whatever operation failed (import, reindex, save) to confirm it's actually resolved, not just hidden.