The error occurs when a holdable cursor is accessed after changing the transaction isolation level that existed when the cursor was declared.
held_cursor_requires_same_isolation_level occurs when you fetch from a holdable cursor after changing the transaction isolation level. Keep the isolation level unchanged for the entire cursor life or re-declare the cursor in the new isolation level to fix the error.
held_cursor_requires_same_isolation_level
PostgreSQL raises error 25008 held_cursor_requires_same_isolation_level when a session tries to fetch from a holdable cursor created under one isolation level after the level has been changed.
The database protects data consistency by binding a holdable cursor to the isolation level at declaration time. Altering the level between DECLARE ...
WITH HOLD and the next FETCH invalidates the cursor.
The error is triggered immediately after a SET TRANSACTION ISOLATION LEVEL statement runs between cursor creation and the next cursor operation. PostgreSQL detects the mismatch and blocks the fetch.
Holdable cursors materialize result sets on commit, so changing isolation rules (e.g., from READ COMMITTED to REPEATABLE READ) would make the materialized snapshot unreliable.
Keep the same isolation level for the entire cursor lifecycle.
Declare the cursor after any SET TRANSACTION statements or move the level change to a new transaction.
Alternatively, CLOSE the existing cursor, issue SET TRANSACTION ISOLATION LEVEL, then DECLARE a new cursor WITH HOLD in the desired level.
Batch jobs often open a holdable cursor, commit, then elevate isolation for a later step.
Rework the flow so the cursor and its consumer share the same level, or replace the cursor with a temporary table.
Interactive sessions using Galaxy can avoid the error by pinning isolation in the editors session tab. Galaxy shows the active level in the status bar, helping engineers catch mismatches early.
Standardize isolation defaults at the connection pool.
Require explicit justification for level changes inside production code reviews.
Use Galaxy Collections to store vetted cursor demos, ensuring teammates follow the same transaction template.
error 0A000 invalid_cursor_state appears when operating on a closed cursor. Keep cursors open or re-declare them.
error 25P02 current_transaction_is_aborted fires after a failed statement. Issue ROLLBACK before reusing the session.
.
No. Only cursors declared WITH HOLD must keep the same isolation level. Non-holdable cursors live only inside the same transaction.
Yes. Once the cursor is closed you can freely issue SET TRANSACTION ISOLATION LEVEL.
All supported versions (9.6 and later) enforce this rule.
Galaxy shows the current isolation level in the session header and warns if you run SET TRANSACTION after opening a holdable cursor.