select open change scope Open full search

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

SQLSTATE / CLASS 42 · SYNTAX ERROR OR ACCESS RULE VIOLATION

invalid_foreign_key

SQLSTATE
42830
Condition name
invalid_foreign_key
Class
Syntax Error or Access Rule Violation
Source macro
ERRCODE_INVALID_FOREIGN_KEY
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>42830 — Invalid foreign key</h1>

At a glance

42830 is invalid_foreign_key: an FK definition cannot find a qualifying unique key on referenced columns. The case references a parent integer column with no unique constraint.

Meaning

Creation checks the parent key before any child row is inserted. The fixed primary is there is no unique constraint matching given keys for referenced table "%s". For an ordinary FK, the referenced column set may match an eligible unique index in a different physical order; the source matcher rejects duplicate referenced columns and requires the right count, uniqueness, validity, and no partial predicate or index expressions. A matching deferrable unique/primary index takes a separate source-only 55000 path. This is definition-time, unlike 23503, and the selected autocommit ALTER leaves IDLE.

Diagnosis

Compare the referenced column set with pg_constraint and pg_index. Check for duplicate references, the number of key columns, unique/primary status, validity, partial predicates, and expressions; physical index order need not equal the FK list order for the ordinary path. Also check indimmediate: a matching deferrable key is rejected with 55000, rather than the selected 42830. Matching data types alone do not make a referenced key eligible.

Response

Add or use an intentional non-deferrable unique key over the referenced column set, then create the FK. Check the business meaning of the parent table's key and desired NULL/MATCH semantics; adding an overly broad unique constraint can change accepted data. Do not reorder a valid index merely to mirror the FK syntax, and do not mistake a partial or expression index for a qualifying key. The case adds UNIQUE (id) then creates one FK. In an explicit transaction, the rejected ALTER TABLE leaves INERROR; roll back or return to a suitable savepoint before retrying. The selected autocommit path returns to IDLE.

Observed diagnostics

The selected tablecmds.c group is explicit ERROR with primary there is no unique constraint matching given keys for referenced table "%s" and no detail or hint. The same matcher has a source-only 55000 (object_not_in_prerequisite_state) variant, cannot use a deferrable unique constraint for referenced table "%s", when the otherwise matching key is deferrable.

Representative case

The registry creates parent and child tables, attempts the FK, adds the parent unique key, creates the valid FK, and counts it.

CREATE TABLE syntax_schema.fk_parent (id integer);
CREATE TABLE syntax_schema.fk_child (parent_id integer);
ALTER TABLE syntax_schema.fk_child ADD CONSTRAINT fk_bad FOREIGN KEY (parent_id) REFERENCES syntax_schema.fk_parent (id);
ALTER TABLE syntax_schema.fk_parent ADD CONSTRAINT fk_parent_id_key UNIQUE (id);
ALTER TABLE syntax_schema.fk_child ADD CONSTRAINT fk_good FOREIGN KEY (parent_id) REFERENCES syntax_schema.fk_parent (id);
SELECT count(*) FROM pg_constraint c JOIN pg_namespace n ON n.oid = c.connamespace WHERE n.nspname = 'syntax_schema_name' AND c.conname = 'fk_good' AND c.contype = 'f';

The selected 18.6 and 10.21 runs passed SQLSTATE, severity, state/recovery, repair, cleanup, and isolated-target stop assertions. See case JSON and authored evidence; private manifest and registry hashes are recorded there.

Versions

The locked catalogue contains this condition from the 7.4 presence bound through the listed snapshots. The selected natural case passed on PostgreSQL 18.6 and 10.21; that bounded result does not infer every intermediate release or every source branch.

Sources

  • src.errcodes.REL_18_6 — fixed definition at 724edf9bde9d356724ad384a2e196edc3c9f80f7; SHA-256 6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba (source).
  • src.invalid-fk.18.6src/backend/commands/tablecmds.c lines 13639–13642 at 724edf9bde9d356724ad384a2e196edc3c9f80f7; blob SHA-256 422dc8e833df4940755973c757e338295822ba3e4c7266c40669f49f96eb15a9 (source).
  • src.invalid-fk.10.23src/backend/commands/tablecmds.c lines 8133–8136 at 02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4; blob SHA-256 6de441c88496c6cf57a836898388085ec08bf69afd70d07acdafd6089b9b5f8c (source).
  • src.invalid-fk-guards.18.6 — complete transformFkeyCheckAttrs in src/backend/commands/tablecmds.c lines 13505–13642 at 724edf9bde9d356724ad384a2e196edc3c9f80f7; blob SHA-256 422dc8e833df4940755973c757e338295822ba3e4c7266c40669f49f96eb15a9 (source).
  • src.invalid-fk-guards.10.23 — complete transformFkeyCheckAttrs in src/backend/commands/tablecmds.c lines 8002–8136 at 02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4; blob SHA-256 6de441c88496c6cf57a836898388085ec08bf69afd70d07acdafd6089b9b5f8c (source).
  • src.calls.REL_18_6 / src.calls.REL_10_23 — fixed call scans, SHA-256 9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf / 00d16d3eb01b71ccf1b245c8f3102f9d0ec9f36fb02777b8dd1b99fcb263040c.
  • manifest.42830 / snippet-registry.42830 — hashes are recorded in evidence/42830.json and each runtime record.

Source evidence

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

42830 is the invalid_foreign_key condition in Class 42.

Method: Read fixed errcodes.txt and locked catalogue metadata.

Limits: Identity does not identify every backend call that can reuse this SQLSTATE.

src.errcodes.REL_18_6

The selected fk_missing_unique_key follows a resolved PostgreSQL source-call group; the complete matcher accepts a duplicate-free referenced column set in any physical order only when the candidate index has the required count, uniqueness, validity, and no predicate or expressions.

Method: Trace the REL_18_6 and REL_10_23 source-call records at the locked commits.

Limits: This is one mechanism boundary, not an exhaustive inventory of the code.

src.invalid-fk.18.6 src.invalid-fk.10.23 src.invalid-fk-guards.18.6 src.invalid-fk-guards.10.23

The same matcher rejects a duplicate referenced-column list with 42830 and rejects an otherwise matching deferrable unique or primary index with OBJECT_NOT_IN_PREREQUISITE_STATE (55000); the latter is source-only in this review.

Method: Read the complete transformFkeyCheckAttrs function in both locked tablecmds.c snapshots.

Limits: The selected runtime covers only the missing-key 42830 case and does not observe the duplicate-list or deferrable branches.

src.invalid-fk-guards.18.6 src.invalid-fk-guards.10.23

The selected fk_missing_unique_key passed on isolated PostgreSQL 18.6 and 10.21 targets.

Method: Run the shared SQL registry and inspect SQLSTATE, severity, state, repair, cleanup, and target stop.

Limits: Scope is limited to these statements, psycopg, and two versions.

manifest.42830 snippet-registry.42830

The locked catalogue records 42830 from the 7.4 presence bound through the listed snapshots; runtime scope is 18.6 and 10.21.

Method: Read generated facts, fixed calls, and selected summaries.

Limits: Definition presence is not an exact behavioral introduction; two runtime versions do not prove every intermediate behavior.

src.errcodes.REL_18_6 src.calls.REL_18_6 src.calls.REL_10_23

Message templates

explicit ERROR · message.fk_missing_unique_key

Primary

there is no unique constraint matching given keys for referenced table "%s"
explicit ERROR · message.deferrable-unique

Primary

cannot use a deferrable unique constraint for referenced table "%s"

Reproduction & repair cases

fk_missing_unique_key · PG 10, 18

Preconditions

  • A runner-owned disposable target is provisioned.

Trigger: Create a foreign key referencing a parent column with no unique constraint.

Expected assertions

  • SQLSTATE is 42830 with the missing referenced unique-key message
  • The failed autocommit session remains IDLE
  • Adding a parent UNIQUE constraint then the FK creates one valid constraint

Repair: Add a deliberate primary/unique key over the referenced columns before defining the FK; matching types alone are insufficient.

Cleanup: Drop the runner schema and both tables.

Recorded runtime evidence

18.6 (Homebrew) · passed

Run: syntax2-42830-latest

{
  "diagnostic": {
    "text": "there is no unique constraint matching given keys for referenced table \"fk_parent\"",
    "context": null,
    "severity": "ERROR",
    "sqlstate": "42830",
    "table_name": null,
    "column_name": null,
    "schema_name": null,
    "source_file": "tablecmds.c",
    "source_line": "13642",
    "message_hint": null,
    "datatype_name": null,
    "exception_type": "InvalidForeignKey",
    "internal_query": null,
    "message_detail": null,
    "constraint_name": null,
    "message_primary": "there is no unique constraint matching given keys for referenced table \"fk_parent\"",
    "source_function": "transformFkeyCheckAttrs",
    "internal_position": null,
    "statement_position": null,
    "severity_nonlocalized": "ERROR"
  },
  "failed_status": "IDLE",
  "repair_status": "IDLE",
  "foreign_key_count": 1,
  "connection_autocommit": true
}
10.21 (Debian 10.21-1.pgdg90+1) · passed

Run: syntax2-42830-pg10

{
  "diagnostic": {
    "text": "there is no unique constraint matching given keys for referenced table \"fk_parent\"",
    "context": null,
    "severity": "ERROR",
    "sqlstate": "42830",
    "table_name": null,
    "column_name": null,
    "schema_name": null,
    "source_file": "tablecmds.c",
    "source_line": "8136",
    "message_hint": null,
    "datatype_name": null,
    "exception_type": "InvalidForeignKey",
    "internal_query": null,
    "message_detail": null,
    "constraint_name": null,
    "message_primary": "there is no unique constraint matching given keys for referenced table \"fk_parent\"",
    "source_function": "transformFkeyCheckAttrs",
    "internal_position": null,
    "statement_position": null,
    "severity_nonlocalized": "ERROR"
  },
  "failed_status": "IDLE",
  "repair_status": "IDLE",
  "foreign_key_count": 1,
  "connection_autocommit": true
}

Definition snapshot: english-manuals:643c7c4b93d620680acf10f8508… · English manual source