0B000ERRORTier 2 — Caution✅ HIGH confidenceinvalid transaction initiation
What this means
SQLSTATE 0B000 is raised when a transaction-control command (e.g., BEGIN) is issued in a context where a new transaction cannot be initiated — for example, inside a function that is already within an implicit transaction.
Why it happens
- 1Issuing BEGIN inside a PL/pgSQL function or trigger (which already runs inside a transaction)
- 2Attempting to start a nested transaction using BEGIN where only SAVEPOINTs are permitted
How to reproduce
Calling BEGIN inside a PL/pgSQL function.
CREATE OR REPLACE FUNCTION bad_begin() RETURNS VOID AS $
BEGIN
BEGIN; -- invalid: already inside a transaction
END;
$ LANGUAGE plpgsql;Fix 1: Use SAVEPOINTs instead of nested BEGIN
When you need nested transaction semantics inside a function.
SAVEPOINT my_save;
-- ... work ...
ROLLBACK TO SAVEPOINT my_save;
RELEASE SAVEPOINT my_save;Why this works
SAVEPOINTs provide rollback-to-point semantics within the enclosing transaction without requiring a new BEGIN.
Fix 2: Use procedures with autonomous transaction control (Postgres 11+)
When the function genuinely needs to commit work independently.
CREATE PROCEDURE my_proc() LANGUAGE plpgsql AS $
BEGIN
-- work ...
COMMIT;
END $;Why this works
Procedures (not functions) can call COMMIT and ROLLBACK in Postgres 11+.
Version notes
Postgres 11+Procedures can use COMMIT/ROLLBACK. Functions still cannot.Sources
📚 Official docs: https://www.postgresql.org/docs/current/errcodes-appendix.html
🔧 Source ref: Class 0B — Invalid Transaction Initiation
Confidence assessment
✅ HIGH confidence
Standard SQLSTATE. The function/procedure distinction for transaction control is stable and well-documented.
See also
🔗 Related errors
📄 Reference pages