24000 — invalid_cursor_state
24000 — invalid_cursor_state
At a glance
24000 means the cursor or portal state does not satisfy the operation. The selected CURRENT OF case declares a valid cursor but tries to update before FETCH has positioned it, producing “cursor … is not positioned on a row”.
| Field | Value |
|---|---|
| SQLSTATE | 24000 |
| Condition | invalid_cursor_state |
| Status | active |
| Known present by | 7.4 |
| Locked snapshots | 9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3 |
| Macros | ERRCODE_INVALID_CURSOR_STATE |
| Aliases | — |
Meaning
WHERE CURRENT OF needs a cursor declared for an updatable query, with a current row selected by FETCH. Declaration alone is not positioning. PostgreSQL uses 24000 for other cursor states too, including non-SELECT, held, non-updatable, or missing FOR UPDATE/SHARE references.
Diagnosis
Record the cursor name and operation, then inspect declaration, transaction lifetime, FETCH direction, and whether the cursor is updatable. In an explicit transaction the selected error leaves INERROR; ROLLBACK restores IDLE. The selected repair updates by primary key, so it verifies transaction recovery and a safe direct repair, not a second DECLARE/FETCH path.
Response
Position the cursor with FETCH before CURRENT OF, or use a deterministic key-based update when that is the intended operation. Keep cursor lifetime and transaction boundaries explicit, and roll back a failed transaction before issuing the repair.
Observed diagnostics
18.6 (Homebrew) / latest:SQLSTATE 24000; primary cursor "item_cursor" is not positioned on a row; after_error INERROR; after_rollback IDLE.
10.21 (Debian 10.21-1.pgdg90+1) / pg10:SQLSTATE 24000; primary cursor "item_cursor" is not positioned on a row; after_error INERROR; after_rollback IDLE.
Representative case
The runner reads these statements from verify/cases/24000/snippets.json (SHA-256 cafca57825378362df0527384614bf658bf86cd3101e1eb520ea0641819f2789) and qualifies the temporary table names; the complete setup, assertions, and cleanup are in the case export.
The SQLSTATE, diagnostic, transaction-state, and repair assertions for this excerpt are produced from the shared registry; structured evidence · case export.
Authored evidence IDs: identity, current-of, runtime. Selected runtime records: runtime.24000-batch1-latest2-20260909.latest, runtime.24000-batch1-pg10-20260909.pg10.
Versions
The locked catalogue observes the condition by 7.4 and in all listed formal snapshots. The selected before-FETCH path passes on 18.6 and 10.21; other cursor-state templates require separate cases.
Related
Compare 25001 active SQL transaction, 25P02 failed SQL transaction, and 34000 invalid cursor name.
Sources
src.errcodes.18.6(SHA-2566e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba)src.calls.REL_18_6(SHA-2569ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf)src.execCurrent.18.6(SHA-25645c8e48b3a5dc46f1014482dc88e0a26c25c3a4c403372112474d9171253d8a9)doc.declare.18.6(SHA-256f1d72befb9a989aa32123560aea784a8bccfcb3d3930804a101d8245e5a3cc95) · official documentationdoc.update.18.6(SHA-25647dd724cd724bd77478215a4853aa1f985996a0e5bba9b2451a1ad1ebb6e51fc) · official documentation