34000
Read PG 18 manual ↗invalid_cursor_name
- SQLSTATE
- 34000
- Condition name
- invalid_cursor_name
- Class
- Invalid Cursor Name
- Source macro
- ERRCODE_INVALID_CURSOR_NAME
- 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
34000 means that a cursor or portal name cannot be resolved in the current backend session. A cursor that was closed, declared on another pooled connection, or ended with its transaction is not the same resource as a cursor with a bad position (24000).
Meaning
The executor's portal path reports cursor "%s" does not exist when FETCH cannot find the named portal. Cursor names are tied to a backend session, and ordinary cursors are tied to a transaction unless declared with an appropriate hold option. A pool checkout therefore must keep declaration and use on the same connection and within the intended transaction boundary.
Diagnosis
Record SQLSTATE, the dynamic cursor name, backend PID, and transaction status. Check the application path for an earlier CLOSE, an implicit commit, a connection return to the pool, or a different session. pg_cursors and the server-side session identity can help when the diagnosis runs on the same backend; a new connection cannot inspect or fetch a cursor owned by the old one.
Response
For an explicit block, rollback after the failed FETCH before issuing more commands. Re-declare the cursor on the same session, or deliberately redesign the workflow to materialize keys/results when work must cross pool checkouts. Use a holdable cursor only when its commit-survival semantics are intended; it does not make a cursor portable between sessions.
Messages
The selected core path uses cursor "%s" does not exist; protocol and PL/pgSQL paths can use portal "%s" or the same cursor wording. The name is dynamic, so use the SQLSTATE and diagnostic fields rather than a full-message equality check across versions and callers.
Representative case
The shared registry in verify/cases/34000/snippets.json (SHA-256 ad5b519e8ca30fd2636b1d0bace32dc18558cccc7b9d360081c27b12a1405f08) declares and closes a cursor, proves the missing-FETCH error, rolls back, and recreates it in the same session. See the public case export and structured evidence.
BEGIN;
DECLARE cursor_name CURSOR FOR SELECT 1;
CLOSE cursor_name;
FETCH cursor_name;
ROLLBACK;
BEGIN;
DECLARE cursor_name CURSOR FOR SELECT 1;
FETCH cursor_name;
CLOSE cursor_name;
COMMIT;
The runner substitutes a unique cursor name. The first FETCH is intentionally after CLOSE; the second FETCH occurs after a new BEGIN and declaration, so the successful row proves lifecycle repair rather than a client-side mock.
The selected case observed 34000 on PostgreSQL 18.6 and 10.21 after closing a named cursor and attempting FETCH. The failed block reached INERROR; rollback followed by a new declaration, fetch, close, and commit returned the session to IDLE.
Versions
The locked catalogue records this condition across the formal snapshots. 18.6 and 10.23 source scans both contain the portal and PL/pgSQL paths; the selected runtime case observes the same SQLSTATE on 18.6 and 10.21, while exact source line and caller wording vary.
Sources
src.errcodes.18.6(SHA-2566e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba)src.portalcmds.18.6(SHA-256e71c5bdb2da67771fb5f42f18b823e8af3ee6c31d5314e97a47ad18f7788bf35)DECLARE documentation· local call scansrc.calls.REL_18_6(SHA-2569ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf)
Source evidence
Evidence belongs to the frozen source and runtime versions listed here. It is not a runtime verification of the selected manual version.
34000 is the invalid_cursor_name condition in Class 34 and shares the undefined-cursor alias.
Method: Read the fixed errcodes.txt row and macro mapping.
Limits: The same SQLSTATE covers several cursor/portal-facing paths.
PerformPortalFetch emits cursor "%s" does not exist when the named portal is absent.
Method: Trace ERRCODE_UNDEFINED_CURSOR in portalcmds.c.
Limits: Other callers use portal or cursor wording; the name is dynamic.
A named cursor belongs to its backend session and transaction lifecycle; closing it or losing its transaction makes a later FETCH invalid.
Method: Compare DECLARE cursor lifecycle with the explicit same-session registry case.
Limits: Holdable cursors and client-side cursor abstractions have additional rules.
The selected 34000 case passed on PostgreSQL 18.6 and 10.21 with the structured SQLSTATE, transaction-state, and repair assertions recorded in the runtime entries.
Method: Read the selected runner summaries and raw outputs tied to the shared snippet registry.
Limits: This covers the selected mechanism only, not all source callers or all driver/pool behavior.
runtime.34000-batch34-20260909.latest runtime.34000-batch34-20260909.pg10
- src/backend/utils/errcodes.txt · REL_18_6 ·
724edf9bde9d356724ad384a2e196edc3c9f80f7 raw/calls/REL_18_6.jsonl· ·- src/backend/commands/portalcmds.c · REL_18_6 ·
724edf9bde9d356724ad384a2e196edc3c9f80f7 - doc/src/sgml/ref/declare.sgml · REL_18_6 ·
724edf9bde9d356724ad384a2e196edc3c9f80f7
Message templates
ERROR · message.cursor-missing
Primary
cursor "%s" does not exist
The portal protocol path uses portal "%s" does not exist.
Reproduction & repair cases
cursor_lifecycle_recovery · PG 10, 18
Preconditions
- A runner-owned disposable target is provisioned.
Trigger: Declare and close a named cursor, attempt to use it again, then recreate it in a new explicit transaction on the same session.
Expected assertions
- SQLSTATE is 34000
- The missing cursor diagnostic is preserved
- The failed block recovers through ROLLBACK
- A recreated cursor can FETCH and COMMIT
Repair: Keep cursor use on the declaring backend session and respect its transaction lifetime; after an error, roll back before recreating it.
Cleanup: Drop the case schema with an owner connection.
Recorded runtime evidence
18.6 (Homebrew) · passed
Run: 34000-batch34-20260909
{
"repair": {
"fetched_row": [
1
]
},
"primary": "cursor \"case_cursor_aa951a82\" does not exist",
"severity": "ERROR",
"sqlstate": "34000",
"statuses": {
"after_error": "INERROR",
"after_repair": "IDLE",
"after_rollback": "IDLE"
},
"connection_autocommit": true
}10.21 (Debian 10.21-1.pgdg90+1) · passed
Run: 34000-batch34-20260909
{
"repair": {
"fetched_row": [
1
]
},
"primary": "cursor \"case_cursor_d0bb43e5\" does not exist",
"severity": "ERROR",
"sqlstate": "34000",
"statuses": {
"after_error": "INERROR",
"after_repair": "IDLE",
"after_rollback": "IDLE"
},
"connection_autocommit": true
}Definition snapshot: english-manuals:f42d4c9463d45d30ea3dc66d08b… · English manual source