Incident brief
Raise exception
PL/pgSQL code called RAISE EXCEPTION with no explicit error code. PostgreSQL reported it under the default PL/pgSQL error code, P0001, and aborted the transaction.
What lands in your log
ERROR: Account balance cannot be negative
In 10 seconds
- What triggers it
- Run a DO block (or function) containing RAISE EXCEPTION 'message'.
- Fix
- Read the message, P0001 is intentional application logic, not a PostgreSQL bug. Fix whatever condition triggered the RAISE.
- Proof
- Reproduced on PostgreSQL 16.14 → A plain RAISE EXCEPTION with a custom message and no ERRCODE was reported as SQLSTATE P0001, and the transaction aborted.
Fix
What to do right now
Application-level steps for this error.
- Read the message, P0001 is intentional application logic, not a PostgreSQL bug. Fix whatever condition triggered the RAISE.
- If callers need to distinguish this error programmatically, give it a specific ERRCODE via RAISE ... USING ERRCODE = '...' instead of relying on the generic P0001.
DO $$
DECLARE
balance numeric := 10;
BEGIN
IF balance < 0 THEN
RAISE EXCEPTION 'Account balance cannot be negative';
END IF;
RAISE NOTICE 'accepted balance %', balance;
END $$;For this error
See this error live on the server
Run these against the affected instance to confirm the diagnosis before you act.
Raise exception comes from PL/pgSQL control flow. Inspect the exact stored function body and line reported in CONTEXT before changing server settings.
Stored PL/pgSQL source for the failing function
Replace the function signature from CONTEXT; this preserves overload identity.
SELECT pg_get_functiondef(to_regprocedure('<schema.function(argument_types)>'));PL/pgSQL assertion setting
Relevant to assertion failures; harmless context for the other PL/pgSQL control-flow errors.
SELECT current_setting('plpgsql.check_asserts', true) AS plpgsql_check_asserts;Why it happens
What PostgreSQL is telling you
The mechanism behind the error, grounded in the official manual, not paraphrased.
PostgreSQL 16 Documentation, Reporting Errors and Messages (43.9.1)
If no condition name nor SQLSTATE is specified in a RAISE EXCEPTION command, the default is to use raise_exception (P0001).Read the full section on postgresql.org →
The raised exception
Per the manual, RAISE EXCEPTION with no condition name or SQLSTATE reports P0001 by default, this is the standard code for a plain, application-defined PL/pgSQL error.Confirming the session still works
The raised exception didn't affect the session, the next statement ran normally.Reproduce & verify
A real, single-session PostgreSQL reproduction
A literal transcript of SQL run against a live PostgreSQL instance in an isolated lab. The commands below are exactly what was executed.
- 1Run a DO block (or function) containing RAISE EXCEPTION 'message'.
- 2SQLSTATE P0001 is reported with that message; the transaction is aborted.
One client: a DO block raises a custom exception with no error code specified.
-- No table needed: RAISE EXCEPTION is pure PL/pgSQL control flow.
SELECT 'no schema required' AS setup_note;DO $$
BEGIN
RAISE EXCEPTION 'Account balance cannot be negative';
END $$;SELECT 1 AS session_still_alive;What PostgreSQL actually returned
setup_note
--------------------
no schema required
(1 row)ERROR: Account balance cannot be negative
CONTEXT: PL/pgSQL function inline_code_block line 3 at RAISE session_still_alive
---------------------
1
(1 row)The deeper lab audit for this error
- Fix that assumes a DO block protects earlier statements: exact SQL, output, and verdict
- A manual-grounded production interpretation of the lab result
Card required. Cancel before day 7 and you are not charged.
Connected
Everything this error touches
Every page this SQLSTATE connects to: the concept that explains it, the runbooks that fix it, the parameters you tune to prevent it, and the sibling errors it travels with. All real cross-references. Jump straight in, or open the full interactive map.
Verification
- Last verified
- 2026-07-16 (Docker lab, PostgreSQL 16.14)
- Verification scope
- Verified against PostgreSQL 16.14 in an isolated lab environment
- Audit status
- reviewed
Went further?
Pro unlocks the second lab proof
Free page stops the bleeding. Pro adds the operational test, SQLSTATE audit, and deeper evidence, same error, more certainty.