RAISE EXCEPTION is a PL/pgSQL statement for throwing custom errors in stored procedures and functions. Understanding proper syntax and usage prevents compilation errors and ensures transactions abort correctly when validation fails.
In PostgreSQL's PL/pgSQL procedural language, RAISE EXCEPTION is a statement that throws a custom error message and aborts the current transaction. When you encounter "Raise exception" errors, it typically means either a syntax error in your RAISE statement, incorrect format string placeholders, or a misuse of the RAISE statement outside of a PL/pgSQL context. RAISE can report messages at different severity levels (DEBUG, LOG, INFO, NOTICE, WARNING, EXCEPTION), with EXCEPTION being the default level that terminates execution.
Ensure the number of % placeholders in your format string matches the number of arguments. Each % will be replaced by the next argument value.
-- Correct: 2 placeholders, 2 arguments
RAISE EXCEPTION 'User % not found with status %', user_id, status;
-- Wrong: 2 placeholders, 1 argument
RAISE EXCEPTION 'User % not found with status %', user_id;RAISE statements are only valid within PL/pgSQL functions, stored procedures, and BEGIN...END blocks. They cannot be used in regular SQL queries.
-- Correct: Inside a function
CREATE OR REPLACE FUNCTION check_user(user_id INT)
RETURNS VOID AS $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM users WHERE id = user_id) THEN
RAISE EXCEPTION 'User % does not exist', user_id;
END IF;
END;
$$ LANGUAGE plpgsql;
-- Wrong: Direct use in SQL
RAISE EXCEPTION 'Invalid input'; -- Will failWhen providing error details, hints, or custom error codes, use the USING clause with proper syntax.
-- Correct: USING clause with multiple options
RAISE EXCEPTION 'Duplicate user ID: %', user_id
USING HINT = 'Please provide a unique user ID',
ERRCODE = 'unique_violation';
-- Wrong: Missing USING keyword
RAISE EXCEPTION 'Invalid input'
HINT = 'Check your parameters';If using custom SQLSTATE/ERRCODE, ensure the code is exactly 5 characters. PostgreSQL provides standard codes, but custom codes should start with a letter (typically 'A') followed by three digits.
-- Correct: Using standard SQLSTATE
RAISE EXCEPTION 'Invalid age' USING ERRCODE = '22003';
-- Correct: Using custom error code
RAISE EXCEPTION 'Business logic error' USING ERRCODE = 'A0001';
-- Wrong: Invalid format
RAISE EXCEPTION 'Error' USING ERRCODE = 'INVALID';Inside an EXCEPTION clause, you can use bare RAISE (with no arguments) to re-throw the caught exception.
CREATE OR REPLACE FUNCTION safe_operation()
RETURNS VOID AS $$
BEGIN
-- Some operation that might fail
PERFORM * FROM invalid_table;
EXCEPTION
WHEN undefined_table THEN
-- Re-throw the same error
RAISE;
END;
$$ LANGUAGE plpgsql;The RAISE statement can reference PostgreSQL's predefined condition names (like unique_violation, division_by_zero, etc.) or custom SQLSTATE codes. When no condition or SQLSTATE is specified, the default error code is RAISE_EXCEPTION (P0001). Transaction behavior is important: RAISE EXCEPTION will roll back the entire transaction, while other levels (NOTICE, WARNING) only report messages. For trigger functions, consider whether you want to abort the operation (EXCEPTION) or just warn (WARNING). In production code, always include meaningful HINT and DETAIL options to help developers debug issues.
0LP01: invalid_grant_operation
How to fix "Invalid grant operation" (0LP01) in PostgreSQL
aggregate functions are not allowed in WHERE clause
How to fix "aggregate functions are not allowed in WHERE clause" in PostgreSQL
2200L: not_an_xml_document
How to fix "2200L: not_an_xml_document" in PostgreSQL
ERROR: ambiguous_parameter
42P08: Ambiguous parameter error
2201F: invalid_argument_for_power_function
Invalid argument for power function (2201F)