42P01
Read PG 18 manual ↗undefined_table
- SQLSTATE
- 42P01
- Condition name
- undefined_table
- Class
- Syntax Error or Access Rule Violation
- Source macro
- ERRCODE_UNDEFINED_TABLE
- Evidence
- Observed at runtime in the source evidence
English SQLSTATE atlas: authored explanations and source/runtime evidence are separate from the manual definitions. View source ↗
At a glance
42P01 is PostgreSQL's undefined_table condition in Class 42, syntax_error_or_access_rule_violation. The name is historical: the failing reference can be a table, view, materialized view, foreign table, or another relation name that the parser cannot resolve in the current namespace.
The ordinary diagnostic is relation "%s" does not exist for an unqualified reference or relation "%s.%s" does not exist for a qualified reference. The parser reports the SQLSTATE before execution of the query; in an autocommit connection the error does not leave a failed transaction behind.
The representative case queries a schema-qualified relation that does not exist, then creates a valid relation and reads it. PostgreSQL 18.6 and the isolated PostgreSQL 10.21 target both returned 42P01, kept the connection IDLE, and accepted the corrected query. The run IDs and assertions are retained in the public evidence JSON.
Meaning and trigger paths
During parse analysis PostgreSQL resolves each relation through the active namespace and search_path. If a qualified name is absent, parse_relation.c emits the two-part message; if an unqualified name is absent, it emits the one-part form. A misspelled name, a migration that has not run, a wrong database, a changed search_path, or a quoted identifier with different case can all lead to this same SQLSTATE.
This is a name-resolution error, not proof that a physical table was deleted. A relation can exist in another schema or database, and a role can lack the privileges needed to see or use it. Conversely, creating a table with a guessed name can conceal a deployment or quoting error.
The parser also uses 42P01 for some invalid references to a FROM item and for a forward reference to a common-table expression, with different detail or hint text. Use the complete message and context to distinguish those forms from a missing relation.
Messages and diagnostics
The runner's operation is a schema-qualified lookup followed by a corrected relation. The harness supplies the disposable schema name; the query shape is:
SELECT * FROM does_not_exist;
CREATE TABLE exists(id integer PRIMARY KEY);
SELECT count(*) FROM exists;
PostgreSQL 18.6 returned:
SQLSTATE: 42P01
severity: ERROR
message_primary: relation "c42p01_missing_relation.does_not_exist" does not exist
source: parse_relation.c / parserOpenTable / line 1480
The PG10 target used the same primary message with source line 1159. The qualified form preserves both schema and relation in the message. For an unqualified reference, the fixed source template is relation "%s" does not exist; a future CTE or invalid FROM reference can add detail or a hint.
Diagnosis
Record SQLSTATE, primary message, detail, hint, statement position, current database, role, and search_path. Check the exact spelling and quoting used by the application. Query pg_class/pg_namespace or to_regclass() through an administrative or appropriately privileged connection to determine where the relation exists.
Compare the deployed migration revision with the connection's database and schema. A pooled connection can carry a different search_path from the session used during setup. If the object is intended to be temporary or session-local, confirm that the query runs in the same session that created it.
The representative error was autocommit and left the connection IDLE; the corrected query returned count 0 and remained IDLE. An explicit transaction can still become INERROR if the missing relation is referenced inside that transaction, so record status rather than assuming that all 42P01 cases are harmless to the surrounding work.
Response and repair
Repair the name-resolution cause in deployment or application configuration:
- Select the intended schema explicitly or set and verify
search_pathfor the session. - Apply the missing migration in the correct database before serving queries.
- Preserve case-sensitive identifiers with exact double quoting, or rename them to a consistent convention after checking dependents.
- Use
to_regclass()or an equivalent preflight only when a missing object is an expected branch; do not silently create a replacement relation for an unexpected deployment failure.
After correcting the relation, run the original query again and verify its result and transaction status. A successful CREATE TABLE or a new connection alone does not prove that every application session resolves the same object.
Versions and boundaries
The catalogue has a definition-presence observation for 42P01 at PostgreSQL 7.4 and through the locked 8.4.22 pre-9.0 definitions, then in every listed formal snapshot through PostgreSQL 18.6 and the PostgreSQL 19 Beta 3 preview. This is a definition-only presence boundary, not an exact implementation introduction or runtime-use claim. No condition definition change is recorded in the scanned range.
The missing-relation case passed on PostgreSQL 18.6 and 10.21. Source line numbers and parser hints differ by release and reference form. This page covers a schema-qualified absent relation and a valid follow-up query, not every namespace or access-rule path that can use 42P01.
Sources
Structured evidence is recorded in the public evidence JSON. Source records are fixed to PostgreSQL commit 724edf9bde9d356724ad384a2e196edc3c9f80f7; runtime records retain both target IDs and structured observations.
src.errcodes.18.6—errcodes.txtsrc.parse-relation.18.6—parse_relation.csrc.namespace.18.6—namespace.cdoc.ddl.18.6— Schemas- Runtime:
42P01-registry-final-20260909on latest and pg10; structured observations are in the public evidence JSON
Source evidence
Evidence belongs to the frozen source and runtime versions listed here. It is not a runtime verification of the selected manual version.
42P01 is the undefined_table condition in Class 42 syntax_error_or_access_rule_violation.
Method: Read the Class 42 section and 42P01 row in the frozen errcodes.txt snapshot.
Limits: The historical condition name covers relation lookup failures beyond a literal table.
The parser reports ERRCODE_UNDEFINED_TABLE with relation "%s.%s" does not exist for a qualified relation and relation "%s" does not exist for an unqualified relation.
Method: Trace namespace.c lookup and parserOpenTable qualified and unqualified error branches in the fixed source, then check the protocol field reference.
Limits: The displayed relation name depends on qualification, search_path, quoting, and the parse context.
src.namespace.18.6 src.parse-relation.18.6 doc.ddl.18.6 doc.protocol.18
A missing relation query returned SQLSTATE 42P01 while autocommit remained IDLE; creating the intended relation and querying it returned count 0 on both targets.
Method: Execute the missing query, inspect diagnostics and status, create the schema-qualified relation, and assert a valid follow-up query.
Limits: This case does not distinguish migration races, search_path changes, permissions, or all relation kinds.
case-manifest.42P01 snippet-registry.42P01.final runtime.42P01-registry-final-20260909.latest runtime.42P01-registry-final-20260909.pg10
The locked catalogue records 42P01 in every listed formal snapshot from 9.0.23 through 18.6 and in 19beta3; pre-9.0 history is not scanned.
Method: Read the manifest snapshots and definition references for the code.
Limits: The first scanned release is a lower bound, not an asserted introduction version.
- src/backend/utils/errcodes.txt · REL_18_6 · lines 372-378
724edf9bde9d356724ad384a2e196edc3c9f80f7 - src/backend/parser/parse_relation.c · REL_18_6 · lines 1473-1501
724edf9bde9d356724ad384a2e196edc3c9f80f7 - src/backend/catalog/namespace.c · REL_18_6 · lines 626-640
724edf9bde9d356724ad384a2e196edc3c9f80f7 - doc/src/sgml/ddl.sgml · PG18-docs · schemas, search_path, and namespace resolution
724edf9bde9d356724ad384a2e196edc3c9f80f7 - doc/src/sgml/protocol.sgml · PG18-docs · ErrorResponse fields
724edf9bde9d356724ad384a2e196edc3c9f80f7 - sources/manifest.lock.json · · snapshots and definition_blobs entries for the 42P01 definition
- verify/cases/42P01/cases.json · · missing_relation
- verify/cases/42P01/snippets.json · · missing_relation ordered SQL
Message templates
explicit ERROR · message.qualified-relation
Primary
relation "%s.%s" does not exist
The qualified form is selected when the parser has a schema-qualified relation reference.
explicit ERROR · message.unqualified-relation
Primary
relation "%s" does not exist
The unqualified form is selected when lookup through the active namespace fails.
Reproduction & repair cases
missing_relation · PG 10, 18
Preconditions
- A disposable schema name that has no relation
Trigger: Select from a relation that does not exist.
Expected assertions
- SQLSTATE is 42P01
- The missing relation is named in the diagnostic
- A valid query succeeds after correcting the relation name
Repair: Check schema qualification, search_path, migrations, and case-sensitive quoting before creating or renaming objects.
Cleanup: Drop the case schema with an owner connection.
Recorded runtime evidence
18.6 (Homebrew) · passed
Run: 42P01-registry-final-20260909
{
"statuses": {
"after_error": "IDLE",
"after_valid_query": "IDLE"
},
"diagnostic": {
"severity": "ERROR",
"sqlstate": "42P01",
"source_file": "parse_relation.c",
"source_line": "1480",
"message_primary": "relation \"c42p01_missing_relation.does_not_exist\" does not exist",
"source_function": "parserOpenTable"
},
"valid_count": 0
}10.21 (Debian 10.21-1.pgdg90+1) · passed
Run: 42P01-registry-final-20260909
{
"statuses": {
"after_error": "IDLE",
"after_valid_query": "IDLE"
},
"diagnostic": {
"severity": "ERROR",
"sqlstate": "42P01",
"source_file": "parse_relation.c",
"source_line": "1159",
"message_primary": "relation \"c42p01_missing_relation.does_not_exist\" does not exist",
"source_function": "parserOpenTable"
},
"valid_count": 0
}Definition snapshot: english-manuals:a4c1a9c483a6f95cb90938127a1… · English manual source