select open change scope Open full search

PG.CENTER connects PostgreSQL documentation, reference, and ecosystem knowledge. Maintained by Pigsty.

SQLSTATE / CLASS 23 · INTEGRITY CONSTRAINT VIOLATION

check_violation

SQLSTATE
23514
Condition name
check_violation
Class
Integrity Constraint Violation
Source macro
ERRCODE_CHECK_VIOLATION
Evidence
Observed at runtime in the source evidence
Analysis & operational context

English SQLSTATE atlas: authored explanations and source/runtime evidence are separate from the manual definitions. View source ↗

<h1>23514 — check_violation</h1>

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.

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

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

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

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

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:

-- 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;

The SQLSTATE, diagnostic, transaction-state, and repair assertions for this excerpt are produced from the checked case registry; see the structured evidence and case export.

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

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.

Sources

Source evidence

Evidence belongs to the frozen source and runtime versions listed here. It is not a runtime verification of the selected manual version.

23514 is check_violation in Class 23.

Method: Read the fixed errcodes row.

Limits: It denotes a failed CHECK or related partition/default constraint path, not only a named table CHECK.

src.errcodes.18.6

The executor reports 23514 with the relation and failed CHECK name when a row evaluates to false.

Method: Trace the executor report group and errtableconstraint metadata.

Limits: A CHECK expression that evaluates to NULL is accepted by PostgreSQL; use NOT NULL when NULL itself is invalid.

src.execMain.18.6 src.calls.REL_18_6

Constraint validation, partition routing, and domain checks can produce different 23514 templates.

Method: Compare the fixed source call groups.

Limits: Repairing data may require a migration or a different partition route; do not assume every 23514 is a duplicate or syntax problem.

src.tablecmds.18.6 src.calls.REL_18_6 src.execPartition.18.6 src.typecmds.18.6 src.execIndexing.18.6

The selected named CHECK case returned 23514 on PG18.6 and PG10.21, identified amount_positive/items, stayed IDLE, and committed a valid row.

Method: Read the selected summaries and raw diagnostics.

Limits: The case does not cover deferred checks, partition routing, domain checks, or validation-time errors.

runtime.23514-batch1-latest-20260909.latest runtime.23514-batch1-pg10-20260909.pg10

Message templates

ERROR · row

Primary

new row for relation "%s" violates check constraint "%s"

Detail

Failing row contains %s.

The failing-row detail is conditional and can be suppressed by context or configuration.

ERROR · partition-no-route

Primary

no partition of relation "%s" found for row

Detail

Partition key of the failing row contains %s.

The partition-key substitution is dynamically built; the path is not the named CHECK template.

ERROR · partition-constraint

Primary

new row for relation "%s" violates partition constraint

Detail

Failing row contains %s.

The relation and failing-row description are dynamic.

ERROR · domain-validation

Primary

column "%s" of table "%s" contains values that violate the new constraint

The column and table identify the existing domain use; this is validation of a new domain constraint.

ERROR · without-overlaps-empty

Primary

empty WITHOUT OVERLAPS value found in column "%s" in relation "%s"

The column and relation are dynamic; this is the empty-value guard, distinct from a conflict with an existing key.

Reproduction & repair cases

check_constraint_insert · PG 10, 18

Preconditions

  • The target table has a named CHECK constraint
  • The inserted value fails that predicate

Trigger: Insert a row whose value violates the CHECK expression.

Expected assertions

  • SQLSTATE is 23514
  • The named relation and constraint are identified
  • A valid row can be inserted after the error

Repair: Correct the value or deliberately revise the constraint after reviewing existing data; do not disable validation to hide a contract violation.

Cleanup: Drop the case schema with an owner connection.

Recorded runtime evidence

18.6 (Homebrew) · passed

Run: 23514-batch1-latest-20260909

{
  "rows": [
    [
      1,
      10
    ],
    [
      2,
      1
    ]
  ],
  "table": "items",
  "detail": "Failing row contains (2, -1).",
  "primary": "new row for relation \"items\" violates check constraint \"amount_positive\"",
  "sqlstate": "23514",
  "constraint": "amount_positive",
  "status_after_error": "IDLE"
}
10.21 (Debian 10.21-1.pgdg90+1) · passed

Run: 23514-batch1-pg10-20260909

{
  "rows": [
    [
      1,
      10
    ],
    [
      2,
      1
    ]
  ],
  "table": "items",
  "detail": "Failing row contains (2, -1).",
  "primary": "new row for relation \"items\" violates check constraint \"amount_positive\"",
  "sqlstate": "23514",
  "constraint": "amount_positive",
  "status_after_error": "IDLE"
}

Definition snapshot: english-manuals:ae866769749b537511ce41ffa39… · English manual source