↑↓ select↵ open⌫ change scopeOpen full search

PG.CENTER connects PostgreSQL documentation, reference, and ecosystem knowledge. Maintained by Pigsty.

Wiki / SQLSTATE

25001 — active_sql_transaction

25001 means the command requires a transaction boundary that the current session violates. The selected case runs VACUUM after BEGIN, receives the exact active-transaction error, rolls back, and then successfully runs VACUUM outside the transaction 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
active_sql_transaction
lang
en
sqlstate
25001

Definition PG 18

25001 — active_sql_transaction

At a glance {#at-a-glance}

25001 means the command requires a transaction boundary that the current session violates. The selected case runs VACUUM after BEGIN, receives the exact active-transaction error, rolls back, and then successfully runs VACUUM outside the transaction block.

Meaning {#meaning}

PostgreSQL uses 25001 for several paths. PreventInTransactionBlock rejects a prohibited utility in an explicit transaction block, subtransaction, or function; the source formats these as %s cannot run inside a transaction block, %s cannot run inside a subtransaction, and %s cannot be executed from a function. Other paths reject creating a logical replication slot after transaction writes, exporting a snapshot from a subtransaction, or setting an imported snapshot after a query. BEGIN inside an already active block is a separate WARNING, so severity and recovery depend on the source path.

Diagnosis {#diagnosis}

Record SQLSTATE, severity, primary message, transaction status, and the command. In the selected case the VACUUM ERROR moves the explicit session to INERROR; only ROLLBACK restores IDLE. For a function or subtransaction report, end that context and issue the command as one top-level utility statement outside any explicit transaction block (for example, a single command on an autocommit connection); retrying inside the same wrapper cannot satisfy PreventInTransactionBlock. For logical-slot and snapshot reports, inspect whether the transaction has writes, a subtransaction, or an earlier query. A WARNING that a transaction is already in progress is not the VACUUM ERROR and does not by itself require rollback. The selected repair then executes VACUUM items outside the transaction block and asserts success plus IDLE, proving the repair boundary instead of merely proving the connection is usable.

Response {#response}

Move a prohibited utility outside the transaction block, function, or subtransaction that violates its contract: issue it as one top-level command outside any explicit transaction block, typically on an autocommit connection. After an ERROR in an explicit transaction, issue ROLLBACK before reuse; do not put the retry inside another BEGIN. A logical replication slot must be created in a transaction with no prior writes; export a snapshot outside a subtransaction, and call SET TRANSACTION SNAPSHOT before any query. Preserve an already active transaction after the WARNING branch instead of rolling it back solely because BEGIN was repeated. Follow the exact source path rather than applying the VACUUM repair mechanically.

Observed diagnostics {#messages}

18.6 (Homebrew) / latest:SQLSTATE 25001; primary VACUUM cannot run inside a transaction block; after_error INERROR; after_rollback IDLE; status_after_vacuum IDLE. 10.21 (Debian 10.21-1.pgdg90+1) / pg10:SQLSTATE 25001; primary VACUUM cannot run inside a transaction block; after_error INERROR; after_rollback IDLE; status_after_vacuum IDLE.

Source message templates {#source-templates}

The selected VACUUM run does not cover these source-backed branches:

  • ERROR %s cannot run inside a subtransaction (the command name is substituted).
  • ERROR %s cannot be executed from a function (the command name is substituted).
  • ERROR cannot create logical replication slot in transaction that has performed writes.
  • ERROR cannot export a snapshot from a subtransaction.
  • ERROR SET TRANSACTION SNAPSHOT must be called before any query.
  • WARNING there is already a transaction in progress.

These templates are source evidence, not additional runtime claims for this case.

Representative case {#case}

In this example, VACUUM is rejected inside an explicit BEGIN block; after ROLLBACK, the same utility succeeds as a standalone command outside that block. The complete setup, assertions, and cleanup are in the case export:

-- create
CREATE TABLE items(id integer PRIMARY KEY, note text NOT NULL);
-- seed
INSERT INTO items VALUES (1, 'seed');
-- begin
BEGIN;
-- trigger
VACUUM items;
-- rollback
ROLLBACK;
-- followup
SELECT 1 AS usable;
-- repair
VACUUM items;

The SQLSTATE, diagnostic, transaction-state, and repair assertions for this excerpt are produced from the checked case registry; see the structured evidence and case export.

Authored evidence IDs: identity, utility-path, other-paths, runtime. Selected runtime records: runtime.25001-batch1-latest2-20260909.latest, runtime.25001-batch1-pg10b-20260909.pg10.

Versions {#versions}

The locked catalogue observes the condition by 7.4 and in all listed formal snapshots. The selected VACUUM case passes on 18.6 and 10.21, including rollback recovery and the successful outside-transaction repair; other 25001 paths are source-backed only.

Related {#related}

Compare 25000 invalid transaction state, 25P02 failed SQL transaction, and 24000 invalid cursor state.

Sources {#sources}

  • src.errcodes.18.6 (SHA-256 6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba)
  • src.calls.REL_18_6 (SHA-256 9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf)
  • src.xact.18.6 (SHA-256 75b012c0b047d1dc905a30975c244beec366e45eac0dbf109fd21bcd611a8e39)
  • src.logical.18.6 (SHA-256 3f1bd4c3e627fe78522c4dc9bacf9fa8200e6c82c2d01f7670706eee102b76d1)
  • src.snapmgr-export.18.6 (SHA-256 b605b69e77a026c143f4cabca079de364b9a8732bfc40f7595be44fb0971ee8)
  • src.snapmgr-set-snapshot.18.6 (SHA-256 b605b69e77a026c143f4cabca079de364b9a8732bfc40f7595be44fb0971ee8)
  • doc.vacuum.18.6 (SHA-256 80ca5592cda7b74938385f84f09faac33574374c1a05d605a2d55982e4cf1bbf) · official documentation

Compare versions

SQLSTATE evidence and recorded runtime versions

cases · vacuum_inside_transaction
{
  "assertions": [
    "SQLSTATE is 25001",
    "The transaction enters INERROR and rollback restores IDLE",
    "The same connection can execute a follow-up query",
    "VACUUM succeeds after rollback outside the transaction block"
  ],
  "case_id": "vacuum_inside_transaction",
  "cleanup": "Drop the case schema with an owner connection.",
  "has_snippet": true,
  "position": 0,
  "preconditions": [
    "A disposable table exists",
    "VACUUM is issued after an explicit BEGIN"
  ],
  "repair": "Run transaction-control-restricted utility commands outside the transaction block; rollback the failed transaction before reuse.",
  "trigger": "Run VACUUM inside an explicit transaction block.",
  "versions": [
    "10",
    "18"
  ]
}
claims · identity
{
  "claim_id": "identity",
  "limits": "The code covers several operations that require a transaction boundary, including subtransactions and function execution.",
  "method": "Read the fixed condition row and macro.",
  "position": 0,
  "runtime": [],
  "sources": [
    "src.errcodes.18.6"
  ],
  "statement": "25001 is active_sql_transaction in Class 25."
}
claims · utility-path
{
  "claim_id": "utility-path",
  "limits": "Some commands are allowed inside transactions; inspect the command-specific contract rather than retrying blindly.",
  "method": "Trace PreventInTransactionBlock and the VACUUM transaction restriction.",
  "position": 1,
  "runtime": [],
  "sources": [
    "src.xact.18.6",
    "doc.vacuum.18.6",
    "src.calls.REL_18_6"
  ],
  "statement": "A utility such as VACUUM cannot run inside an explicit transaction block; xact.c formats the statement name into the 25001 primary message."
}
claims · other-paths
{
  "claim_id": "other-paths",
  "limits": "Severity and recovery depend on the exact path; do not treat every 25001 as an ERROR.",
  "method": "Read all fixed 25001 report groups selected by the source call scan.",
  "position": 2,
  "runtime": [],
  "sources": [
    "src.xact.18.6",
    "src.calls.REL_18_6",
    "src.logical.18.6",
    "src.snapmgr-export.18.6",
    "src.snapmgr-set-snapshot.18.6"
  ],
  "statement": "The same SQLSTATE has distinct source templates for subtransactions, function execution, logical replication slots after writes, and snapshot operations; a WARNING “there is already a transaction in progress” is a separate severity path."
}
claims · runtime
{
  "claim_id": "runtime",
  "limits": "The case covers VACUUM in a transaction, not logical replication slots, snapshot export, function calls, or warning handling.",
  "method": "Read the selected summaries and raw diagnostics.",
  "position": 3,
  "runtime": [],
  "sources": [
    "runtime.25001-batch1-latest2-20260909.latest",
    "runtime.25001-batch1-pg10b-20260909.pg10"
  ],
  "statement": "The selected VACUUM case returned 25001 on PG18.6 and PG10.21, entered INERROR, recovered after ROLLBACK, accepted a follow-up query, and then completed VACUUM outside the transaction block with the connection IDLE."
}
messages · transaction-block
{
  "limits": "The %s substitution is the command name; this is one ERROR path for 25001.",
  "message_id": "transaction-block",
  "path": "",
  "position": 0,
  "raw": {
    "id": "transaction-block",
    "limits": "The %s substitution is the command name; this is one ERROR path for 25001.",
    "primary_template": "%s cannot run inside a transaction block",
    "severity_source": "ERROR",
    "sources": [
      "src.xact.18.6"
    ],
    "sqlstate": "25001"
  },
  "severity": "ERROR",
  "sources": [
    "src.xact.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "cannot run inside a transaction block",
      "position": 0,
      "role": "",
      "template": "%s cannot run inside a transaction block"
    }
  ]
}
messages · subtransaction
{
  "limits": "The format string is source-backed; substitutions are supplied by the executing path.",
  "message_id": "subtransaction",
  "path": "",
  "position": 1,
  "raw": {
    "id": "subtransaction",
    "limits": "The format string is source-backed; substitutions are supplied by the executing path.",
    "primary_template": "%s cannot run inside a subtransaction",
    "severity_source": "ERROR",
    "sources": [
      "src.xact.18.6"
    ],
    "sqlstate": "25001"
  },
  "severity": "ERROR",
  "sources": [
    "src.xact.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "cannot run inside a subtransaction",
      "position": 0,
      "role": "",
      "template": "%s cannot run inside a subtransaction"
    }
  ]
}
messages · already-in-progress
{
  "limits": "This source path is explicitly WARNING and must not be presented as the VACUUM ERROR template.",
  "message_id": "already-in-progress",
  "path": "",
  "position": 2,
  "raw": {
    "id": "already-in-progress",
    "limits": "This source path is explicitly WARNING and must not be presented as the VACUUM ERROR template.",
    "primary_template": "there is already a transaction in progress",
    "severity_source": "WARNING",
    "sources": [
      "src.xact.18.6"
    ],
    "sqlstate": "25001"
  },
  "severity": "WARNING",
  "sources": [
    "src.xact.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "there is already a transaction in progress",
      "position": 0,
      "role": "",
      "template": "there is already a transaction in progress"
    }
  ]
}
messages · function
{
  "limits": "The %s substitution is the command name; this branch is rejected because it is called from a function.",
  "message_id": "function",
  "path": "",
  "position": 3,
  "raw": {
    "id": "function",
    "limits": "The %s substitution is the command name; this branch is rejected because it is called from a function.",
    "primary_template": "%s cannot be executed from a function",
    "severity_source": "ERROR",
    "sources": [
      "src.xact.18.6"
    ],
    "sqlstate": "25001"
  },
  "severity": "ERROR",
  "sources": [
    "src.xact.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "cannot be executed from a function",
      "position": 0,
      "role": "",
      "template": "%s cannot be executed from a function"
    }
  ]
}
messages · logical-slot-after-write
{
  "limits": "The source condition is a transaction that already has a top-level transaction ID from writes.",
  "message_id": "logical-slot-after-write",
  "path": "",
  "position": 4,
  "raw": {
    "id": "logical-slot-after-write",
    "limits": "The source condition is a transaction that already has a top-level transaction ID from writes.",
    "primary_template": "cannot create logical replication slot in transaction that has performed writes",
    "severity_source": "ERROR",
    "sources": [
      "src.logical.18.6"
    ],
    "sqlstate": "25001"
  },
  "severity": "ERROR",
  "sources": [
    "src.logical.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "cannot create logical replication slot in transaction that has performed writes",
      "position": 0,
      "role": "",
      "template": "cannot create logical replication slot in transaction that has performed writes"
    }
  ]
}
messages · snapshot-subtransaction
{
  "limits": "The branch rejects export from the current subtransaction; prior committed subtransactions are handled separately by the source.",
  "message_id": "snapshot-subtransaction",
  "path": "",
  "position": 5,
  "raw": {
    "id": "snapshot-subtransaction",
    "limits": "The branch rejects export from the current subtransaction; prior committed subtransactions are handled separately by the source.",
    "primary_template": "cannot export a snapshot from a subtransaction",
    "severity_source": "ERROR",
    "sources": [
      "src.snapmgr-export.18.6"
    ],
    "sqlstate": "25001"
  },
  "severity": "ERROR",
  "sources": [
    "src.snapmgr-export.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "cannot export a snapshot from a subtransaction",
      "position": 0,
      "role": "",
      "template": "cannot export a snapshot from a subtransaction"
    }
  ]
}
messages · snapshot-after-query
{
  "limits": "The command must be at the top level of a fresh transaction before a query establishes the snapshot.",
  "message_id": "snapshot-after-query",
  "path": "",
  "position": 6,
  "raw": {
    "id": "snapshot-after-query",
    "limits": "The command must be at the top level of a fresh transaction before a query establishes the snapshot.",
    "primary_template": "SET TRANSACTION SNAPSHOT must be called before any query",
    "severity_source": "ERROR",
    "sources": [
      "src.snapmgr-set-snapshot.18.6"
    ],
    "sqlstate": "25001"
  },
  "severity": "ERROR",
  "sources": [
    "src.snapmgr-set-snapshot.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "SET TRANSACTION SNAPSHOT must be called before any query",
      "position": 0,
      "role": "",
      "template": "SET TRANSACTION SNAPSHOT must be called before any query"
    }
  ]
}
runtimes · runtime.25001-batch1-latest2-20260909.latest · 18.6 (Homebrew) · passed
{
  "cases": [
    "vacuum_inside_transaction"
  ],
  "limits": "",
  "position": 0,
  "raw": {
    "case_manifest": {
      "path": "verify/cases/25001/cases.json",
      "sha256": "2a5fad757733e23fd68df23270c4b0dfe108ff9ba0e1ab33c4a69e85c46c7ce1"
    },
    "cases": [
      "vacuum_inside_transaction"
    ],
    "id": "runtime.25001-batch1-latest2-20260909.latest",
    "observed": {
      "after_error": "INERROR",
      "after_rollback": "IDLE",
      "primary": "VACUUM cannot run inside a transaction block",
      "sqlstate": "25001",
      "status_after_vacuum": "IDLE",
      "usable": 1,
      "vacuum_outside_transaction": true
    },
    "raw": "verify/results/25001-batch1-latest2-20260909/latest/raw.jsonl",
    "raw_sha256": "0b164ca0eab22ccc7ad5d18ed6201072049d2b7ba49e8cc99ba65aae172e1ec0",
    "run_id": "25001-batch1-latest2-20260909",
    "server_version": "18.6 (Homebrew)",
    "server_version_num": 180006,
    "snippet_registry": {
      "path": "verify/cases/25001/snippets.json",
      "sha256": "0fc4277a4e2f59e78e54a1fed1ec0efef6bd0d3bd97180e03df596677e847f03"
    },
    "status": "passed",
    "summary": "verify/results/25001-batch1-latest2-20260909/latest/summary.json",
    "summary_sha256": "544bd0ec303a15036fe848468ed90f2674d5c2212e520bf6be2413bfdc91f200",
    "target": "latest"
  },
  "run_id": "25001-batch1-latest2-20260909",
  "runtime_id": "runtime.25001-batch1-latest2-20260909.latest",
  "server_version": "18.6 (Homebrew)",
  "status": "passed",
  "target": "latest"
}
runtimes · runtime.25001-batch1-pg10b-20260909.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
  "cases": [
    "vacuum_inside_transaction"
  ],
  "limits": "",
  "position": 1,
  "raw": {
    "case_manifest": {
      "path": "verify/cases/25001/cases.json",
      "sha256": "2a5fad757733e23fd68df23270c4b0dfe108ff9ba0e1ab33c4a69e85c46c7ce1"
    },
    "cases": [
      "vacuum_inside_transaction"
    ],
    "id": "runtime.25001-batch1-pg10b-20260909.pg10",
    "observed": {
      "after_error": "INERROR",
      "after_rollback": "IDLE",
      "primary": "VACUUM cannot run inside a transaction block",
      "sqlstate": "25001",
      "status_after_vacuum": "IDLE",
      "usable": 1,
      "vacuum_outside_transaction": true
    },
    "raw": "verify/results/25001-batch1-pg10b-20260909/pg10/raw.jsonl",
    "raw_sha256": "1efa43a93beca206fe048de038e4538694746fece446eb129a81fb8e36aa2740",
    "run_id": "25001-batch1-pg10b-20260909",
    "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
    "server_version_num": 100021,
    "snippet_registry": {
      "path": "verify/cases/25001/snippets.json",
      "sha256": "0fc4277a4e2f59e78e54a1fed1ec0efef6bd0d3bd97180e03df596677e847f03"
    },
    "status": "passed",
    "summary": "verify/results/25001-batch1-pg10b-20260909/pg10/summary.json",
    "summary_sha256": "498a7229697ff6f46b6bbb135c3f79215cbb5442e9ce2400f651bb5efb91b151",
    "target": "pg10"
  },
  "run_id": "25001-batch1-pg10b-20260909",
  "runtime_id": "runtime.25001-batch1-pg10b-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.xact.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/access/transam/xact.c",
  "position": 2,
  "sha256": "75b012c0b047d1dc905a30975c244beec366e45eac0dbf109fd21bcd611a8e39",
  "source_id": "src.xact.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/access/transam/xact.c#L3654-L3677"
}
sources · doc.vacuum.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/sql-vacuum.html",
  "kind": "upstream_source",
  "location": "",
  "path": "doc/src/sgml/ref/vacuum.sgml",
  "position": 3,
  "sha256": "80ca5592cda7b74938385f84f09faac33574374c1a05d605a2d55982e4cf1bbf",
  "source_id": "doc.vacuum.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/ref/vacuum.sgml"
}
sources · src.logical.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/replication/logical/logical.c",
  "position": 4,
  "sha256": "3f1bd4c3e627fe78522c4dc9bacf9fa8200e6c82c2d01f7670706eee102b76d1",
  "source_id": "src.logical.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/replication/logical/logical.c#L444-L446"
}
sources · src.snapmgr-export.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/time/snapmgr.c",
  "position": 5,
  "sha256": "b605b69e77a026c143f4cabca079de364b9a8732bfc40f7595be44fb0971ee8",
  "source_id": "src.snapmgr-export.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/time/snapmgr.c#L1152-L1154"
}
sources · src.snapmgr-set-snapshot.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/utils/time/snapmgr.c",
  "position": 6,
  "sha256": "b605b69e77a026c143f4cabca079de364b9a8732bfc40f7595be44fb0971ee8",
  "source_id": "src.snapmgr-set-snapshot.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/time/snapmgr.c#L1409-L1411"
}

Source references

Full definition and evidence JSON

Definition sources

center · PostgreSQL 18 · english-manuals:3d854acb6b32084a7a74bdad3093c4e30fa1c82d986ac74170fe99968f415652

Text language: en · english-manuals:3d854acb6b32084a7a74bdad3093c4e30fa1c82d986ac74170fe99968f415652