# 23514 — check_violation

> PostgreSQL SQLSTATE 23514: check_violation with CHECK and partition validation boundaries.
---

# 23514 — check_violation

## At a glance {#at-a-glance}

`23514` means a CHECK or related row constraint evaluated as false. The selected named constraint is `amount_positive`; the server reports the table and constraint and the invalid row detail.

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| Field | Value |
| --- | --- |
| SQLSTATE | `23514` |
| Condition | `check_violation` |
| Status | `active` |
| Known present by | `7.4` |
| Locked snapshots | `9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| Macros | `ERRCODE_CHECK_VIOLATION` |
| Aliases | `—` |

<!-- source facts: data/errcodes/23514.json -->
<!-- END SQLSTATE FACTS -->

## Meaning {#meaning}

For an ordinary table row, the executor evaluates the CHECK expression and reports `23514` when it is false; a CHECK expression that evaluates to NULL passes PostgreSQL’s CHECK rule, so add NOT NULL when NULL itself is forbidden. Partition routing can report `no partition of relation ... found for row` with a partition-key detail, while a partition constraint check reports a partition-constraint message. Domain validation has its own “values that violate the new constraint” template, and an empty `WITHOUT OVERLAPS` value is another source path. These are the same SQLSTATE with different mechanisms and messages.

## Diagnosis {#diagnosis}

Record `constraint_name`, `table_name`, and the failing-row or partition-key detail. Re-evaluate the expression with the actual types and NULL behavior, including implicit casts and trigger changes. For a partition error, inspect the partition bounds and the route selected by the key; for a domain or validation error, identify the schema object whose rule was checked. The selected autocommit case became `IDLE` after the error; explicit transactions still require the caller’s rollback or handler boundary.

## Response {#response}

Correct the value or the business rule, then retry. If the rule is changing, validate existing rows and deploy the new constraint deliberately; do not disable a CHECK to hide bad data. For partitions, route the row to a partition whose bound admits it rather than treating the error as a generic row retry.

## Observed diagnostics {#messages}

`18.6 (Homebrew) / latest`:SQLSTATE `23514`; primary `new row for relation "items" violates check constraint "amount_positive"`; DETAIL `Failing row contains (2, -1).`; status_after_error `IDLE`.
`10.21 (Debian 10.21-1.pgdg90+1) / pg10`:SQLSTATE `23514`; primary `new row for relation "items" violates check constraint "amount_positive"`; DETAIL `Failing row contains (2, -1).`; status_after_error `IDLE`.

## Representative case {#case}

In this example, the first insert violates the named CHECK because `amount` is `-1`; changing it to `1` is the concrete repair. The complete setup, assertions, and cleanup are in the [case export](../data/cases/23514.json):

<!-- BEGIN SQLSTATE SNIPPET: check_constraint_insert -->
```sql
-- create
CREATE TABLE items(id integer PRIMARY KEY, amount integer CONSTRAINT amount_positive CHECK (amount > 0));
-- seed
INSERT INTO items VALUES (1, 10);
-- trigger
INSERT INTO items VALUES (2, -1);
-- repair
INSERT INTO items VALUES (2, 1);
-- verify
SELECT id, amount FROM items ORDER BY id;
```
<!-- END SQLSTATE SNIPPET -->

The SQLSTATE, diagnostic, transaction-state, and repair assertions for this excerpt are produced from the checked case registry; see the [structured evidence](../data/evidence/23514.json) and [case export](../data/cases/23514.json).

Authored evidence IDs: `identity`, `row-path`, `schema-path`, `runtime`. Selected runtime records: `runtime.23514-batch1-latest-20260909.latest`, `runtime.23514-batch1-pg10-20260909.pg10`.

## Versions {#versions}

The locked catalogue observes the condition by `7.4` and in all listed formal snapshots. The selected runtime covers one immediate named CHECK INSERT on 18.6 and 10.21. It does not cover partition routing, domain validation, validation-time errors, or the `WITHOUT OVERLAPS` path. The fixed DDL documentation describes CHECK as passing when its expression is true or NULL; it does not define a `DEFERRABLE` CHECK path.

## Related {#related}

Compare [23502 NOT NULL violation](../23502/), [23P01 exclusion violation](../23p01/), and [23505 unique violation](../23505/).

## Sources {#sources}

- [`src.errcodes.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt) (SHA-256 `6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba`)
- `src.calls.REL_18_6` (SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf`)
- [`src.execMain.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/executor/execMain.c#L2076-L2081) (SHA-256 `33b97337fa23a649c5e7a092e1bd405a54e8503529236c62c9d5bb93a1774a8d`)
- [`src.tablecmds.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/tablecmds.c#L6502-L6532) (SHA-256 `422dc8e833df4940755973c757e338295822ba3e4c7266c40669f49f96eb15a9`)
- [`src.execPartition.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/executor/execPartition.c#L328-L335) (SHA-256 `97951428f673d4eb6dd23141817874c29640aaac0d6dc74015c993cbd0636dd6`)
- [`src.typecmds.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/typecmds.c#L3288-L3293) (SHA-256 `60d1e9754646e100f6b74aa367ad8c2c52386c400df721707423d329209c47eb`)
- [`src.execIndexing.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/executor/execIndexing.c#L1176-L1181) (SHA-256 `24c80553ab4b28d7d2a288dd9196c8db9459c7f308853cd8c8c939485e15f199`)
- [`doc.ddl-constraints.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/ddl.sgml) (SHA-256 `ce1919d9236f2e71672660e1a347146472e966e4d19b77fde5ae345dd1db6ec7`) · [official documentation](https://www.postgresql.org/docs/18/ddl-constraints.html)
