42P19
Read PG 18 manual ↗invalid_recursion
- SQLSTATE
- 42P19
- Condition name
- invalid_recursion
- Class
- Syntax Error or Access Rule Violation
- Source macro
- ERRCODE_INVALID_RECURSION
- Evidence
- Source path confirmed
English SQLSTATE atlas: authored explanations and source/runtime evidence are separate from the manual definitions. View source ↗
At a glance
42P19 (invalid_recursion) Recursive query structure is checked before the recursive term can run.
Meaning
Recursive-query validation rejects a recursive term whose structure cannot be evaluated safely. Core 18.6 checks aggregate use in the recursive term, the required non-recursive UNION [ALL] recursive form, and recursive-reference context and multiplicity. The selected aggregate guard is about aggregates (p_hasAggs); it does not justify saying that every window function is forbidden.
Diagnosis
Read the query shape rather than only the CTE name. Separate the anchor term from the recursive term, count references to the recursive query, and inspect whether a reference appears in a forbidden recursive context such as a subquery or the nullable side of an outer join: for LEFT JOIN that is the right side, for RIGHT JOIN the left side, and for FULL JOIN both sides; the preserved side of a one-sided outer join is not covered by that guard. Also check INTERSECT/EXCEPT contexts. Identify actual aggregates in the recursive term; do not classify every window expression as this error. This distinguishes structural recursion errors from 42P18 type inference failures.
Response
Rewrite the CTE into one non-recursive anchor followed by one UNION or UNION ALL recursive term, keep one recursive reference in an allowed context, and move aggregation outside the recursive step when needed. Validate termination and result cardinality before retrying. If this ERROR occurs inside an explicit transaction, ROLLBACK or ROLLBACK TO a pre-error savepoint before sending the rewritten query.
Messages
Representative source messages include: message: aggregate functions are not allowed in a recursive query's recursive term; message: recursive query "%s" does not have the form non-recursive-term UNION [ALL] recursive-term; message: recursive reference to query "%s" must not appear more than once. Placeholders are filled by the actual object, column, or parameter.
Versions
The locked catalogue shows this condition by PostgreSQL 8.4.0; behavior here is fixed to PostgreSQL 18.6 source. Catalogue presence is a range boundary, not proof that every message or feature began in that release.
Sources
Source messages, line anchors, and evidence limits are recorded in authored evidence.
src/backend/parser/parse_agg.c:1329-1333(fixed source)src/backend/parser/parse_cte.c:940-944(fixed source)src/backend/parser/parse_cte.c:1072-1077(fixed source)src/backend/parser/parse_cte.c:1056-1069(fixed source)
Source evidence
Evidence belongs to the frozen source and runtime versions listed here. It is not a runtime verification of the selected manual version.
42P19 is the invalid_recursion condition in Class 42.
Method: Read fixed REL_18_6 errcodes.txt and locked facts.
Limits: Identity does not enumerate all source branches or client failures.
Core 18.6 checks aggregate use in the recursive term, the required non-recursive UNION [ALL] recursive form, and recursive-reference context and multiplicity. The selected aggregate guard is p_hasAggs; it does not establish that every window function is forbidden. Outer-join context applies to the nullable side (LEFT right, RIGHT left, FULL both), while the preserved side of a one-sided join is not covered by that guard.
Method: Read selected resolved REL_18_6 report groups and message roles.
Limits: Representative confirmed core paths only; not exhaustive historical or extension coverage.
src.call.42P19.e59c077eba1a4a52a69a6d97 src.call.42P19.e6e0586856ee8989b006f7ae src.call.42P19.3b25492c51b06d773f237993 src.call.42P19.recursion-context
Locked catalogue snapshots show this condition by PostgreSQL 8.4.0; source behavior here is fixed at PostgreSQL 18.6.
Method: Read locked catalogue facts and definition snapshot.
Limits: First observed release is a lower bound, not precise behavioral introduction.
- src/backend/utils/errcodes.txt · REL_18_6 · line 345
724edf9bde9d356724ad384a2e196edc3c9f80f7 - src/backend/parser/parse_agg.c · REL_18_6 · lines 1329-1333
724edf9bde9d356724ad384a2e196edc3c9f80f7 - src/backend/parser/parse_cte.c · REL_18_6 · lines 940-944
724edf9bde9d356724ad384a2e196edc3c9f80f7 - src/backend/parser/parse_cte.c · REL_18_6 · lines 1072-1077
724edf9bde9d356724ad384a2e196edc3c9f80f7 - src/backend/parser/parse_cte.c · REL_18_6 · lines 1056-1069
724edf9bde9d356724ad384a2e196edc3c9f80f7 raw/calls/REL_18_6.jsonl· ·
Message templates
ERROR · message.variant-1
Primary
aggregate functions are not allowed in a recursive query's recursive term
Placeholders remain dynamic source fields; no concrete runtime value is claimed.
ERROR · message.variant-2
Primary
recursive query "%s" does not have the form non-recursive-term UNION [ALL] recursive-term
Placeholders remain dynamic source fields; no concrete runtime value is claimed.
ERROR · message.variant-3
Primary
recursive reference to query "%s" must not appear more than once
Placeholders remain dynamic source fields; no concrete runtime value is claimed.
Reproduction & repair cases
No reproduction case is attached to this condition.
Recorded runtime evidence
No runtime observation is attached to this entry.
Definition snapshot: english-manuals:e5e4315659d43c6982c00ed5ec7… · English manual source