Skip to content

P0001 — raise_exception

PostgreSQL uses SQLSTATE P0001 for a PL/pgSQL RAISE EXCEPTION with no explicit condition or SQLSTATE. Diagnose the application control flow and recover at the correct transaction boundary.

At a glance

P0001 is the raise_exception condition in PostgreSQL’s PL/pgSQL-specific Class P0. A RAISE EXCEPTION statement with no condition name and no explicit SQLSTATE defaults to this code. The message is supplied by the function author, so P0001 is usually an application or procedure control signal rather than a diagnosis of one server subsystem.

The level and code are separate choices. EXCEPTION is the default RAISE level and normally aborts the current transaction. NOTICE, WARNING, INFO, LOG, and DEBUG generate messages without that exception behavior; an explicit ERRCODE can also choose a different SQLSTATE. Always capture the severity and SQLSTATE together.

The representative case plpgsql_raise_exception creates a function containing RAISE EXCEPTION 'calibration exception', calls it, and then runs SELECT 1 on the same autocommit connection. PostgreSQL 18.6 and 10.21 both returned P0001, preserved the message, left the connection IDLE, and accepted the follow-up query. The SQL excerpt below is the complete ordered function, call, and follow-up from the shared snippet registry; the runner owns the schema-qualified name and cleanup.

Field Value
SQLSTATE P0001
Condition raise_exception
Status active
Known present by 8.0.0
Locked snapshots 9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3
Macros ERRCODE_RAISE_EXCEPTION
Aliases

Meaning and trigger paths

The 18.6 directory places P0001 in Class P0, PL/pgSQL Error, and names it raise_exception. The class is PostgreSQL-specific. In the PL/pgSQL executor, the default code is assigned only when no code was supplied and the level is at least ERROR; the executor then reports the caller’s message and optional detail, hint, and object fields.

The syntax supports several distinct paths:

  • RAISE EXCEPTION 'message' uses P0001 by default.
  • RAISE EXCEPTION condition_name uses the condition’s SQLSTATE, so it need not be P0001.
  • RAISE EXCEPTION SQLSTATE '5-character-code' or RAISE ... USING ERRCODE = ... lets a procedure expose a domain-specific contract. PostgreSQL permits user-chosen five-character codes other than 00000.
  • A lower level such as RAISE WARNING 'message' emits a message at that priority. It is not the same transaction event as RAISE EXCEPTION, even if the caller chooses an explicit error code.

The no-argument RAISE; form is re-raise control inside an active exception handler. Its behavior and SQLSTATE are determined by the exception being re-raised; it is not a new default P0001 event.

Messages and diagnostics

The representative registry operation is:

CREATE FUNCTION raise_exception_case() RETURNS void
LANGUAGE plpgsql AS $$
BEGIN
    RAISE EXCEPTION 'calibration exception';
END
$$;
SELECT raise_exception_case();
SELECT 1;

The function name is schema-qualified and generated by the test executor in the actual run. The observed 18.6 diagnostic was:

SQLSTATE: P0001
severity: ERROR
message_primary: calibration exception
context: PL/pgSQL function ...raise_exception_case() line 3 at RAISE
source: pl_exec.c / exec_stmt_raise / line 3923

There is no universal English primary message for P0001; the function supplies it. USING MESSAGE, DETAIL, HINT, COLUMN, CONSTRAINT, DATATYPE, TABLE, and SCHEMA can add structured diagnostics. Localized message text can change while SQLSTATE remains stable, so branch on P0001 and inspect the structured fields rather than parsing the primary string.

Diagnosis

First determine whether the code came from an intentional RAISE EXCEPTION or from a different domain condition that the function explicitly selected. Record SQLSTATE, localized and nonlocalized severity, primary message, detail, hint, context, source location, and the statement that called the function. In a PL/pgSQL handler, SQLSTATE and SQLERRM identify the active exception, while GET STACKED DIAGNOSTICS retrieves its fields.

Then locate the function branch and its transaction context. A failed call in autocommit ends that statement and leaves the connection ready for another command, as the representative case shows. A call inside an explicit transaction normally leaves the transaction aborted until the client issues ROLLBACK or rolls back to a savepoint. The server connection is not necessarily terminated.

An EXCEPTION clause changes the boundary. The protected body runs in a subtransaction; when it errors, persistent changes made by that body are rolled back before the first matching condition handler runs, while changes made outside it remain. WHEN OTHERS matches every error except QUERY_CANCELED and ASSERT_FAILURE; it is broad and should not be used as a substitute for identifying the intended P0001 path.

Response

Use P0001 when the procedure intentionally exposes the generic PL/pgSQL raise contract. If callers need to distinguish validation, conflict, quota, or another business outcome, choose and document an appropriate SQLSTATE and add DETAIL or HINT that helps the caller act. Do not turn unrelated server errors into P0001 merely to simplify application code.

At the client boundary, roll back an explicit transaction before issuing unrelated commands, or use a savepoint when the caller can safely isolate the function call. In PL/pgSQL, prefer a narrow handler such as WHEN raise_exception or WHEN SQLSTATE 'P0001' when the recovery is specific. If a broad handler is required, preserve RETURNED_SQLSTATE, MESSAGE_TEXT, PG_EXCEPTION_DETAIL, PG_EXCEPTION_HINT, and context before deciding whether to continue or re-raise.

The natural RAISE EXCEPTION case is safe to demonstrate because it exercises the intended PL/pgSQL mechanism. That does not make P0001 evidence of a server fault; it is an explicit exception raised by the function.

Versions

The catalogue records P0001 in the locked 8.0.0–8.4.22 pre-9.0 formal sources, every formal snapshot from 9.0.23 through 18.6, and the 19 Beta 3 preview. The same-tag REL8_1_4 errcodes.sgml table already lists P0001 as raise_exception, confirming that condition-name observation by 8.1.4. The class title is PL/pgSQL Error (PostgreSQL-specific error class) in the 9.0 header view and changes to PL/pgSQL Error in the 9.1 text definition. Candidate source gaps remain for 7.0–7.3; these are observed catalogue boundaries, not asserted implementation introduction dates.

The fixed 18.6 source commit is 724edf9bde9d356724ad384a2e196edc3c9f80f7. The default RAISE EXCEPTION rule is documented for PostgreSQL 18 and source-confirmed in the 18.6 executor. The representative case passed on PostgreSQL 18.6 and 10.21; it does not test every custom code, handler, or transaction mode.

P0000plpgsql_error is the broader PL/pgSQL-specific class condition. P0002no_data_found, P0003too_many_rows, and P0004assert_failure are distinct P0 conditions. 25P02in_failed_sql_transaction describes the follow-on state after an unhandled exception aborts an explicit transaction. XX000internal_error is a server internal-error code and should not be used as a synonym for an intentional RAISE.

Sources

The structured evidence is recorded in the public evidence JSON. Source records are pinned to PostgreSQL commit 724edf9bde9d356724ad384a2e196edc3c9f80f7; runtime records retain the shared snippet registry, both target summaries, and run P0001-snippet-registry-final-20260909.