42P11ERRORTier 2 — Caution✅ HIGH confidenceinvalid cursor definition
What this means
SQLSTATE 42P11 is raised when a cursor definition is structurally invalid — for example, using FOR UPDATE on a cursor query that contains a JOIN, DISTINCT, or aggregate which makes the cursor non-updatable.
Why it happens
- 1DECLARE ... FOR UPDATE on a cursor query that is not simple enough to support row-level locking (contains JOINs, DISTINCT, GROUP BY, etc.)
How to reproduce
FOR UPDATE cursor with a JOIN.
DECLARE my_cursor CURSOR FOR
SELECT e.*, d.name FROM employees e JOIN departments d ON e.dept_id = d.id
FOR UPDATE;Fix 1: Remove FOR UPDATE from cursors with JOINs
When row locking is not needed.
DECLARE my_cursor CURSOR FOR
SELECT e.*, d.name FROM employees e JOIN departments d ON e.dept_id = d.id;Why this works
FOR UPDATE is only supported on simple single-table cursor queries.
Fix 2: Separate the cursor query to a single table for locking
When row locking is required.
DECLARE my_cursor CURSOR FOR
SELECT * FROM employees FOR UPDATE;Why this works
Use a simple single-table cursor with FOR UPDATE, then join other tables in the processing loop if needed.
Sources
📚 Official docs: https://www.postgresql.org/docs/current/errcodes-appendix.html
🔧 Source ref: Class 42 — Syntax Error or Access Rule Violation (Postgres-specific)
Confidence assessment
✅ HIGH confidence
Postgres-specific. Stable across versions.
See also
🔗 Related errors
📄 Reference pages