PG
PRO
25001ERRORTier 1 — Safe✅ HIGH confidence

active SQL transaction

Category: Invalid Transaction StateVersions: All Postgres versions

What this means

A command that cannot run inside an active transaction block (such as CREATE DATABASE, VACUUM, or certain system-administration commands) was issued while a transaction was in progress.

Why it happens

  1. 1CREATE DATABASE or DROP DATABASE issued inside a BEGIN...COMMIT block
  2. 2VACUUM, CLUSTER, or REINDEX DATABASE issued inside a transaction
  3. 3Calling a function that internally executes a transaction-incompatible command
  4. 4ORM or migration framework wrapping all DDL in transactions and using a command that is transaction-incompatible

How to reproduce

CREATE DATABASE is issued inside an explicit transaction block.

trigger — this will ERROR
BEGIN;
CREATE DATABASE newdb; -- triggers 25001
ERROR: CREATE DATABASE cannot run inside a transaction block

Fix 1: Issue the command outside a transaction block

Always — transaction-incompatible commands must run in autocommit mode.

fix
-- End the current transaction first:
COMMIT; -- or ROLLBACK;

-- Then run the command in autocommit mode (no BEGIN):
CREATE DATABASE newdb;

Why this works

Commands like CREATE DATABASE operate at the cluster level and manipulate the database template or global catalog entries. These operations cannot be rolled back by the transaction manager and are therefore prohibited inside transactions. Running outside a transaction means each statement is auto-committed.

Fix 2: Configure your migration tool to run the command outside a transaction

When a migration framework wraps all DDL in transactions.

fix
-- In Flyway: use custom migration script with:
-- SET statement_timeout TO 0;
-- And mark the script as non-transactional (-- disableInTransaction in Flyway)

-- In Django migrations: use database_backwards / RunSQL with atomic=False

-- In psql, use set AUTOCOMMIT on before issuing the command

Why this works

Most migration tools run each migration in a transaction for atomicity. For transaction-incompatible commands, the tool must be configured to suppress the BEGIN that wraps the migration. The command then executes in autocommit mode via the server's default behaviour for statements outside a transaction block.

What not to do

Wrap CREATE DATABASE in a DO block to try to bypass the restriction

Why it's wrong: The restriction applies regardless of how the command is invoked; PL/pgSQL DO blocks still run inside the calling transaction context.

Sources

📚 Official docs: https://www.postgresql.org/docs/current/errcodes-appendix.html

📚 Feature docs: https://www.postgresql.org/docs/current/sql-createdatabase.html

🔧 Source ref: src/backend/tcop/utility.c — PreventInTransactionBlock()

📖 Further reading: CREATE DATABASE

Confidence assessment

✅ HIGH confidence

Stable and well-documented. The set of transaction-incompatible commands is well-known and consistent across versions. The migration tool workaround advice is general; specific configuration varies by tool version.

See also

⚙️ This error reference was generated with AI assistance and reviewed for accuracy. Examples are provided to illustrate common scenarios and may not cover every case. Always test fixes in a development environment before applying to production. Spotted an error? Suggest a correction →