Skip to content
SQL errors / “Failing Row Contains” — Read a SQL Constraint Error
SQL error

“Failing Row Contains” — Read a SQL Constraint Error

An INSERT or UPDATE broke a NOT NULL or CHECK rule on the table. The detail line shows the row.

The exact message
PostgreSQL
DETAIL: Failing row contains (...)

Printed under NOT NULL and CHECK errors, listing every value in the rejected row. Unique and foreign key errors print Key (...) instead.

DuckDB
Constraint Error: CHECK constraint failed on table signup with expression CHECK((plan IN ('free', 'pro')))

Names the table and the rule, but prints no failing-row line.

MySQL
Check constraint 'signup_chk_1' is violated.

Names the constraint only; no row values.

SQLite
CHECK constraint failed: plan in ('free', 'pro')

Quotes the rule's expression; no row values.

The symptom

PostgreSQL rejects an INSERT or UPDATE and adds a detail line like "Failing row contains (...)". The statement did not quietly skip that row; it failed because the row would break a rule on the table. PostgreSQL prints that line for a NOT NULL or CHECK failure. A unique or foreign key failure gets a Key (...) line instead, naming only the key.

The garden_shop practice tables load straight from CSV and carry no constraints of their own, so the bench below declares a small table with three rules on it: a primary key, a unique email, and a check on the plan. Only one of them fires, and it is the kind that produces a failing-row line. Read the message to find out which, then switch to the fix.

DuckDB reports this as Constraint Error: CHECK constraint failed on table signup with expression CHECK((plan IN ('free', 'pro'))). The second row asks for a team plan the rule does not allow. Notice what the message gives you: the table and the rule that fired. It does not print the row at all. PostgreSQL, where this page's title phrase comes from, names the constraint (signup_plan_check) and adds DETAIL: Failing row contains (2, ben@example.com, team)., every value in the rejected row, which is why the phrase became a common thing to search for.

Read the line before the row

The values inside failing row contains are evidence, not the root cause. The real clue is the line above it, which names the violated constraint. Only a NOT NULL or CHECK failure prints the row; a UNIQUE, primary key, or foreign key failure names the key instead. Either way, the constraint tells you where to go next.

Error clue What it usually means Go to
not-null constraint A required column would be NULL. NOT NULL constraint failed
check constraint A row breaks a business rule the table enforces. CHECK constraint failed
duplicate key A unique or primary key value already exists. Duplicate key violates primary key
foreign key A child row points to a missing parent, or a parent has child rows. Violates foreign key constraint
generated column You supplied a value for a column the database computes. Cannot insert into a generated column

Debug the rejected row

Turn the values from the error into a small SELECT. Confirm what is missing or duplicated before changing the data.

Check for a duplicate key
select customer_id, first_name, last_name, email
from customers
where customer_id = 5;

A row comes back, so customer_id 5 is taken: an insert claiming it would collide. Run the same query for a key the error named and getting nothing back tells you the opposite story: that is the shape of a missing parent rather than a duplicate.

Check for a missing parent row
select customer_id
from customers
where customer_id = 42;

-- No rows: an order for customer_id 42 would violate a foreign
-- key that requires customers.customer_id.

Fix the data or the rule

Most of the time, the fix is the data: provide the required value, use a valid status, choose a new key, or create the parent row before the child row. Change the table constraint only when the rule itself is wrong.

The query that fails
create or replace table signup (
  id integer primary key,
  email varchar unique not null,
  plan varchar check (plan in ('free', 'pro'))
);
insert into signup values (1, 'ada@example.com', 'free');
insert into signup values (2, 'ben@example.com', 'team');

Running it raises CHECK constraint failed on table signup with expression CHECK((plan IN ('free', 'pro'))).

The corrected query
create or replace table signup (
  id integer primary key,
  email varchar unique not null,
  plan varchar check (plan in ('free', 'pro'))
);
insert into signup values (1, 'ada@example.com', 'free');
insert into signup values (2, 'ben@example.com', 'pro');

Open the corrected query in the playground

Fix a missing required value
insert into customers (customer_id, first_name, email)
values (42, 'Ada', 'ada@example.com');
PostgreSQL wording

The exact phrase "Failing row contains" is PostgreSQL's, and it only appears under NOT NULL and CHECK errors. Other databases use different words, but the debugging habit is the same: identify the constraint, inspect the row, then fix the data or the rule.

How other engines word it

Engine Message
PostgreSQL DETAIL: Failing row contains (...) Printed under NOT NULL and CHECK errors, listing every value in the rejected row. Unique and foreign key errors print Key (...) instead.
DuckDB Constraint Error: CHECK constraint failed on table signup with expression CHECK((plan IN ('free', 'pro'))) Names the table and the rule, but prints no failing-row line.
MySQL Check constraint 'signup_chk_1' is violated. Names the constraint only; no row values.
SQLite CHECK constraint failed: plan in ('free', 'pro') Quotes the rule's expression; no row values.

Which engines show you the row

Engines usually identify the rule or object that rejected the write. They differ in whether they name a declared constraint and whether they include the rejected values, which determines how much investigation remains.

Engine Shows the rejected row? What you get
PostgreSQL For NOT NULL and CHECK A DETAIL: Failing row contains (...) line with every value in the row. Unique and foreign key errors show only the key, as in Key (email)=(ada@example.com) already exists.
DuckDB Partly Names the key and value for a duplicate, as in Duplicate key "email: ada@example.com", and the table and rule for a CHECK failure, but never the rest of the row.
SQL Server Partly Names the constraint and the table; the value only sometimes.
MySQL Partly Names the column or the duplicate value, as in Duplicate entry '1' for key.
SQLite No Names the constraint and the column only, as in UNIQUE constraint failed: signup.email.

Related errors

Learn more