25006 — read_only_sql_transaction
25006 is returned when a command would write in a read-only transaction. The selected case issues CREATE TABLE after SET TRANSACTION READ ONLY, observes INERROR, rolls back, and creates the table after leaving the read-only block.
English manual coverage begins with PostgreSQL 8.1. Source history and runtime observations have their own recorded version boundaries.
Reading PG 18·Select a recorded version
- aliases
- Unknown
- class name
- Invalid Transaction State
- condition name
- read_only_sql_transaction
- lang
- en
- sqlstate
- 25006
Definition PG 18
25006 — read_only_sql_transaction
At a glance {#at-a-glance}
25006 is returned when a command would write in a read-only transaction. The selected case issues CREATE TABLE after SET TRANSACTION READ ONLY, observes INERROR, rolls back, and creates the table after leaving the read-only block.
Meaning {#meaning}
The code covers several guards. PreventCommandIfReadOnly formats the command name into cannot execute %s in a read-only transaction; the fixed source also has recovery-only messages for temporary tables and replication origins. The selected case covers the ordinary explicit read-only transaction path, while a standby or recovery path can use a different command-specific message.
Diagnosis {#diagnosis}
Record the exact command, SQLSTATE, severity, and transaction status. Before retrying, inspect the effective SHOW transaction_read_only and, for a server-level boundary, pg_is_in_recovery(); also identify whether a pool routed this connection to a standby. In the selected run, CREATE TABLE returns 25006 and leaves the explicit block INERROR; ROLLBACK is required before the same session can be used. A later CREATE TABLE outside the read-only block succeeds.
Response {#response}
Decide whether the operation belongs in a read-only transaction. If it must write, use a read/write transaction on the primary or run it outside the read-only block, and roll back the failed block before returning the connection to a pool. A standby or recovery-only 25006 path requires routing the operation to the primary; retrying the same write on the same target cannot change its access mode.
Source messages {#messages}
The core utility template is cannot execute %s in a read-only transaction. The same utility guard uses cannot execute %s during recovery on a recovery target; recovery-only temporary-table and replication-origin paths have their own fixed text. %s is the executing command name, so these are not context-free static messages.
Observed diagnostics {#observed}
18.6 (Homebrew) / latest: SQLSTATE 25006; primary cannot execute CREATE TABLE in a read-only transaction; INERROR → IDLE; repaired relation count 0; final IDLE.
10.21 (Debian 10.21-1.pgdg90+1) / pg10: SQLSTATE 25006; primary cannot execute CREATE TABLE in a read-only transaction; INERROR → IDLE; repaired relation count 0; final IDLE.
Representative case {#case}
The runner reads the setup, read-only transaction, rollback, and outside-block repair statements below from the shared registry; complete assertions, environment, and cleanup are in case export.
-- create
CREATE TABLE items(id integer PRIMARY KEY, note text NOT NULL);
-- begin
BEGIN;
-- read_only
SET TRANSACTION READ ONLY;
-- trigger
CREATE TABLE blocked(id integer PRIMARY KEY);
-- rollback
ROLLBACK;
-- repair
CREATE TABLE blocked(id integer PRIMARY KEY);
-- verify
SELECT count(*) FROM blocked;
The SQLSTATE, diagnostics, states, and repair assertions for this excerpt come from the shared registry (SHA-256 62db30e401b1f72fa50958d0ac612b2b1eb636299532dd1ad246c167e4f9fadf); structured evidence.
Authored evidence IDs: identity, utility-path, other-paths, runtime. Selected runtime records: runtime.25006-batch2-latest-20260909.latest, runtime.25006-batch2-pg10-20260909.pg10.
Versions and limits {#versions}
The selected CREATE TABLE case passes on PostgreSQL 18.6 and 10.21 with the same primary text, INERROR → IDLE recovery, and a successful repaired relation. Other 25006 source paths remain outside this runtime case.
Related {#related}
25P02 failed SQL transaction, 25001 active SQL transaction, 25P03 idle-in-transaction timeout.
Sources {#sources}
src.errcodes.18.6(SHA-2566e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba)src.calls.REL_18_6—raw/calls/REL_18_6.jsonl(SHA-2569ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf)src.utility.18.6(SHA-2567aae5d07628b6debf8456d1d4ea96f28912232192e56ea25773b4c4b61235a00)src.namespace.18.6(SHA-2568c9e6a99e84fa2cec8a9b1de2ecbe3966a13f4ad68c6ccfbfb8134a754d73e56)src.origin.18.6(SHA-25681e5d5b4539b67bb372f0f0a05395af900c322cdbcec8a4b1f358333a16e6518)doc.set-transaction.18.6(SHA-25633554463a2c9da1cf2c72cc27d4647d557204bb13a03cfeccb1b83f237a46589) · official documentation
Compare versions
SQLSTATE evidence and recorded runtime versions
cases · read_only_transaction
{
"assertions": [
"SQLSTATE is 25006",
"The CREATE TABLE read-only diagnostic is exact",
"The failed transaction is INERROR, ROLLBACK restores IDLE",
"The table can be created after leaving read-only mode"
],
"case_id": "read_only_transaction",
"cleanup": "Drop the case schema with an owner connection.",
"has_snippet": true,
"position": 0,
"preconditions": [
"A runner-owned disposable target is provisioned."
],
"repair": "Follow the explicit transaction or source boundary described by the case.",
"trigger": "Run CREATE TABLE after SET TRANSACTION READ ONLY.",
"versions": [
"10",
"18"
]
}claims · identity
{
"claim_id": "identity",
"limits": "The same code covers more than one read-only/recovery guard.",
"method": "Read the fixed condition row and macro.",
"position": 0,
"runtime": [],
"sources": [
"src.errcodes.18.6"
],
"statement": "25006 is read_only_sql_transaction in Class 25."
}claims · utility-path
{
"claim_id": "utility-path",
"limits": "The %s substitution is command-specific; recovery and parallel-operation paths have their own conditions/messages.",
"method": "Trace PreventCommandIfReadOnly and the documented read-only command restrictions.",
"position": 1,
"runtime": [],
"sources": [
"src.utility.18.6",
"src.calls.REL_18_6",
"doc.set-transaction.18.6"
],
"statement": "PreventCommandIfReadOnly formats the SQL command name into “cannot execute %s in a read-only transaction”; CREATE TABLE is one ordinary utility path."
}claims · other-paths
{
"claim_id": "other-paths",
"limits": "Those recovery paths were not constructed by the selected ordinary read-only transaction case.",
"method": "Read the additional fixed source report groups.",
"position": 2,
"runtime": [],
"sources": [
"src.namespace.18.6",
"src.origin.18.6"
],
"statement": "The fixed source also uses 25006 for temporary-table creation during recovery and replication-origin manipulation during recovery."
}claims · runtime
{
"claim_id": "runtime",
"limits": "The case covers the ordinary explicit read-only utility path, not recovery-only temporary-table or replication-origin paths.",
"method": "Read the selected summaries and structured diagnostics.",
"position": 3,
"runtime": [],
"sources": [
"runtime",
"runtime.25006-batch2-latest-20260909.latest",
"runtime.25006-batch2-pg10-20260909.pg10"
],
"statement": "The selected read-only CREATE TABLE case returned 25006 on PostgreSQL 18.6 and 10.21, entered INERROR, recovered after ROLLBACK, and created the relation outside the read-only transaction."
}claims · recovery-utility
{
"claim_id": "recovery-utility",
"limits": "The %s substitution is command-specific; the selected runtime did not run on a standby or recovery target.",
"method": "Read the recovery guard and resolved report group in utility.c.",
"position": 4,
"runtime": [],
"sources": [
"src.utility.18.6",
"src.calls.REL_18_6"
],
"statement": "The same fixed utility source uses 25006 during recovery with the command-specific message \"cannot execute %s during recovery\"; this is separate from the selected ordinary read-only transaction path."
}messages · utility
{
"limits": "The %s substitution is the command name.",
"message_id": "utility",
"path": "",
"position": 0,
"raw": {
"id": "utility",
"limits": "The %s substitution is the command name.",
"primary_template": "cannot execute %s in a read-only transaction",
"severity_source": "ERROR",
"sources": [
"src.utility.18.6"
],
"sqlstate": "25006"
},
"severity": "ERROR",
"sources": [
"src.utility.18.6"
],
"templates": [
{
"kind": "primary",
"literal": "cannot execute in a read-only transaction",
"position": 0,
"role": "",
"template": "cannot execute %s in a read-only transaction"
}
]
}messages · utility-recovery
{
"limits": "Recovery-only utility path; %s is the command name and this was not the selected ordinary read-only case.",
"message_id": "utility-recovery",
"path": "",
"position": 1,
"raw": {
"id": "utility-recovery",
"limits": "Recovery-only utility path; %s is the command name and this was not the selected ordinary read-only case.",
"primary_template": "cannot execute %s during recovery",
"severity_source": "ERROR",
"sources": [
"src.utility.18.6"
],
"sqlstate": "25006"
},
"severity": "ERROR",
"sources": [
"src.utility.18.6"
],
"templates": [
{
"kind": "primary",
"literal": "cannot execute during recovery",
"position": 0,
"role": "",
"template": "cannot execute %s during recovery"
}
]
}messages · recovery-temp
{
"limits": "A recovery-only path; not the selected case.",
"message_id": "recovery-temp",
"path": "",
"position": 2,
"raw": {
"id": "recovery-temp",
"limits": "A recovery-only path; not the selected case.",
"primary_template": "cannot create temporary tables during recovery",
"severity_source": "ERROR",
"sources": [
"src.namespace.18.6"
],
"sqlstate": "25006"
},
"severity": "ERROR",
"sources": [
"src.namespace.18.6"
],
"templates": [
{
"kind": "primary",
"literal": "cannot create temporary tables during recovery",
"position": 0,
"role": "",
"template": "cannot create temporary tables during recovery"
}
]
}messages · recovery-origin
{
"limits": "A recovery-only path; not the selected case.",
"message_id": "recovery-origin",
"path": "",
"position": 3,
"raw": {
"id": "recovery-origin",
"limits": "A recovery-only path; not the selected case.",
"primary_template": "cannot manipulate replication origins during recovery",
"severity_source": "ERROR",
"sources": [
"src.origin.18.6"
],
"sqlstate": "25006"
},
"severity": "ERROR",
"sources": [
"src.origin.18.6"
],
"templates": [
{
"kind": "primary",
"literal": "cannot manipulate replication origins during recovery",
"position": 0,
"role": "",
"template": "cannot manipulate replication origins during recovery"
}
]
}runtimes · runtime.25006-batch2-latest-20260909.latest · 18.6 (Homebrew) · passed
{
"cases": [
"read_only_transaction"
],
"limits": "",
"position": 0,
"raw": {
"case_manifest": {
"path": "verify/cases/25006/cases.json",
"sha256": "2009137faa2d1ebbbfa4dedfc1be073f9ea41b4bedd6c0acb34f3215ae37e25f"
},
"case_status": "passed",
"cases": [
"read_only_transaction"
],
"id": "runtime.25006-batch2-latest-20260909.latest",
"observed": {
"after_error": "INERROR",
"after_rollback": "IDLE",
"final_status": "IDLE",
"primary": "cannot execute CREATE TABLE in a read-only transaction",
"repair_relation": "\"c25006_read_only_transaction\".\"blocked\"",
"rows_after_repair": 0,
"sqlstate": "25006"
},
"raw": "verify/results/25006-batch2-latest-20260909/latest/raw.jsonl",
"raw_sha256": "b506359510adfe87c3fb8dbf50ed863b7fcdaad5b6bbb7ebf910ecec38c80780",
"run_id": "25006-batch2-latest-20260909",
"server_version": "18.6 (Homebrew)",
"server_version_num": 180006,
"snippet_registry": {
"path": "verify/cases/25006/snippets.json",
"sha256": "62db30e401b1f72fa50958d0ac612b2b1eb636299532dd1ad246c167e4f9fadf"
},
"status": "passed",
"summary": "verify/results/25006-batch2-latest-20260909/latest/summary.json",
"summary_sha256": "24fcf5d910c49c64eb3277bc4642190fe182f1ae2b731b2dffb0a5474c0189fe",
"target": "latest",
"target_status": "passed"
},
"run_id": "25006-batch2-latest-20260909",
"runtime_id": "runtime.25006-batch2-latest-20260909.latest",
"server_version": "18.6 (Homebrew)",
"status": "passed",
"target": "latest"
}runtimes · runtime.25006-batch2-pg10-20260909.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
"cases": [
"read_only_transaction"
],
"limits": "",
"position": 1,
"raw": {
"case_manifest": {
"path": "verify/cases/25006/cases.json",
"sha256": "2009137faa2d1ebbbfa4dedfc1be073f9ea41b4bedd6c0acb34f3215ae37e25f"
},
"case_status": "passed",
"cases": [
"read_only_transaction"
],
"id": "runtime.25006-batch2-pg10-20260909.pg10",
"observed": {
"after_error": "INERROR",
"after_rollback": "IDLE",
"final_status": "IDLE",
"primary": "cannot execute CREATE TABLE in a read-only transaction",
"repair_relation": "\"c25006_read_only_transaction\".\"blocked\"",
"rows_after_repair": 0,
"sqlstate": "25006"
},
"raw": "verify/results/25006-batch2-pg10-20260909/pg10/raw.jsonl",
"raw_sha256": "8aa0068ea4575ffc24bc86d329a039a63c80f5e218cad36e9e6bfa3075c8c731",
"run_id": "25006-batch2-pg10-20260909",
"server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
"server_version_num": 100021,
"snippet_registry": {
"path": "verify/cases/25006/snippets.json",
"sha256": "62db30e401b1f72fa50958d0ac612b2b1eb636299532dd1ad246c167e4f9fadf"
},
"status": "passed",
"summary": "verify/results/25006-batch2-pg10-20260909/pg10/summary.json",
"summary_sha256": "9de68a1e3ec84530fad088519fe71f009fde4dfefd02bd27e15096fb6c5b498a",
"target": "pg10",
"target_status": "passed"
},
"run_id": "25006-batch2-pg10-20260909",
"runtime_id": "runtime.25006-batch2-pg10-20260909.pg10",
"server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
"status": "passed",
"target": "pg10"
}sources · src.errcodes.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "upstream_source",
"location": "",
"path": "src/backend/utils/errcodes.txt",
"position": 0,
"sha256": "6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba",
"source_id": "src.errcodes.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt"
}sources · src.calls.REL_18_6
{
"commit": "",
"docs_url": "",
"kind": "local_artifact",
"location": "",
"path": "raw/calls/REL_18_6.jsonl",
"position": 1,
"sha256": "9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf",
"source_id": "src.calls.REL_18_6",
"tag": "",
"url": ""
}sources · src.utility.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "upstream_source",
"location": "",
"path": "src/backend/tcop/utility.c",
"position": 2,
"sha256": "7aae5d07628b6debf8456d1d4ea96f28912232192e56ea25773b4c4b61235a00",
"source_id": "src.utility.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/utility.c#L397-L448"
}sources · src.namespace.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "upstream_source",
"location": "",
"path": "src/backend/catalog/namespace.c",
"position": 3,
"sha256": "8c9e6a99e84fa2cec8a9b1de2ecbe3966a13f4ad68c6ccfbfb8134a754d73e56",
"source_id": "src.namespace.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/catalog/namespace.c#L4418-L4437"
}sources · src.origin.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "upstream_source",
"location": "",
"path": "src/backend/replication/logical/origin.c",
"position": 4,
"sha256": "81e5d5b4539b67bb372f0f0a05395af900c322cdbcec8a4b1f358333a16e6518",
"source_id": "src.origin.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/replication/logical/origin.c#L189-L200"
}sources · doc.set-transaction.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "https://www.postgresql.org/docs/18/sql-set-transaction.html",
"kind": "upstream_source",
"location": "",
"path": "doc/src/sgml/ref/set_transaction.sgml",
"position": 5,
"sha256": "33554463a2c9da1cf2c72cc27d4647d557204bb13a03cfeccb1b83f237a46589",
"source_id": "doc.set-transaction.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/ref/set_transaction.sgml#L131-L145"
}Source references
Full definition and evidence JSON
Definition sources
center · PostgreSQL 18 · english-manuals:7845b825032955824315db9b8ee306470412f9a99ab3f92ae12eb8009ce1a2c5
Text language: en · english-manuals:7845b825032955824315db9b8ee306470412f9a99ab3f92ae12eb8009ce1a2c5