Common SQL Errors

PostgreSQL Error 25006: read_only_sql_transaction Explained

August 4, 2025

PostgreSQL raises error 25006 read_only_sql_transaction when a write statement runs inside a transaction that has been marked read only.

Sign up for the latest in common SQL errors from the Galaxy Team!
Welcome to the Galaxy, Guardian!
You'll be receiving a confirmation email

Follow us on twitter :)
Oops! Something went wrong while submitting the form.

What is PostgreSQL error 25006 (read_only_sql_transaction)?

PostgreSQL error 25006 read_only_sql_transaction appears when a session issues INSERT, UPDATE, DELETE, or DDL while the current transaction is read only. End the transaction or start a new one without the READ ONLY flag, or connect to a writable primary instead of a read replica.

Error Highlights

Typical Error Message

PostgreSQL Error 25006 read_only_sql_transaction

Error Type

Transaction State Error

Language

PostgreSQL

Symbol

read_only_sql_transaction

Error Code

25006

SQL State

Explanation

Table of Contents

What is PostgreSQL error 25006 (read_only_sql_transaction)?

Error 25006 fires when PostgreSQL detects an attempt to modify data within a transaction that is declared READ ONLY. The server blocks the operation to protect data consistency on read replicas or in explicitly read only sessions.

The error stops any INSERT, UPDATE, DELETE, or DDL statement until the transaction ends or is restarted in read write mode.

Fixing it quickly is critical because no changes will persist while the transaction remains read only.

What Causes This Error?

The most common trigger is connecting to a hot standby or logical read replica that forbids writes by default. Applications that fail over to a replica unknowingly run into 25006 on their first write.

The error also occurs when a client executes SET TRANSACTION READ ONLY or runs inside a function that called SET LOCAL default_transaction_read_only = on.

Superuser maintenance scripts can accidentally inherit this mode.

How to Fix PostgreSQL error 25006

First, confirm whether the session is on a replica or on the primary. If on a replica, reconnect to the primary node for write activity. If on the primary, commit or roll back the current read only transaction and start a fresh one without the READ ONLY clause.

If your code sets default_transaction_read_only, change it to READ WRITE or remove the directive.

In ORMs, disable automatic read only transactions for write paths.

Common Scenarios and Solutions

Cloud read replicas like AWS RDS or GCP AlloyDB reject writes. Switch the connection string to the writer endpoint to clear the error.

During maintenance, administrators sometimes SET default_transaction_read_only = on to prevent writes. Remember to reset it afterward with SET ... = off.

Background jobs that wrap logic in BEGIN READ ONLY inadvertently prevent later write statements.

Split read and write logic into separate transactions to avoid the clash.

Best Practices to Avoid This Error

Always label replica connection strings clearly and configure your pooler to route writes only to the primary. Monitor pg_stat_activity to catch write attempts on replicas in real time.

Inside Galaxy, you can tag connections as read only or read write.

The editor warns when an INSERT or DDL targets a read only handle, helping developers correct the mistake before execution.

Related Errors and Solutions

Error 25007 cannot_deferrable_sql_transaction arises from DEFERRABLE misuse in the same transaction-state class. Error 25001 active_sql_transaction appears when SET commands require no active transaction. The fixes involve ending the incorrect transaction state before issuing the statement.

.

Common Causes

Related Errors

FAQs

Can I force a single statement to bypass read only mode?

No. You must end the read only transaction and start a new one in READ WRITE mode because PostgreSQL applies the flag to the entire transaction block.

Does error 25006 mean data was lost?

No data is lost. PostgreSQL halts the write before execution, so existing rows remain unchanged.

Why do I see the error only in production?

Many production setups use read replicas for scaling reads. Local development usually connects directly to a writable primary, masking the issue.

How does Galaxy help avoid this error?

Galaxy lets you label connections as read replica or primary. The IDE highlights potentially unsafe writes against read replicas and suggests switching to a writable connection.

Start Querying with the Modern SQL Editor Today!
Welcome to the Galaxy, Guardian!
You'll be receiving a confirmation email

Follow us on twitter :)
Oops! Something went wrong while submitting the form.

Check out some other errors

Trusted by top engineers on high-velocity teams
Aryeo Logo
Assort Health
Curri
Rubie Logo
Bauhealth Logo
Truvideo Logo