25001
PostgreSQLERRORCommonInvalid Transaction StateHIGH confidence

active SQL transaction

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
trigger — this will error
BEGIN;
CREATE DATABASE newdb; -- triggers 25001

expected output

ERROR:  CREATE DATABASE cannot run inside a transaction block

Fix 1

Issue the command outside a transaction block

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

Issue the command outside a transaction block
-- 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 When a migration framework wraps all DDL in transactions.

Configure your migration tool to run the command outside a transaction
-- 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

The restriction applies regardless of how the command is invoked; PL/pgSQL DO blocks still run inside the calling transaction context.

Sources
Official documentation ↗

src/backend/tcop/utility.c — PreventInTransactionBlock()

CREATE DATABASE

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All PostgreSQL errors