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.
ERROR: syntax error at end of input
Syntax error at end of input in PostgreSQL
Bind message supplies N parameters but prepared statement requires M
Bind message supplies N parameters but prepared statement requires M in PostgreSQL
Multidimensional arrays must have sub-arrays with matching dimensions
Multidimensional arrays must have sub-arrays with matching dimensions
ERROR: value too long for type character varying
Value too long for type character varying
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL