39P01
PostgreSQLERRORNotableExternal Routine Invocation ExceptionHIGH confidence
trigger protocol violated
What this means
SQLSTATE 39P01 is a Postgres-specific error raised when a trigger function violates the trigger calling protocol — for example, returning an incompatible value from a row-level trigger (must return a RECORD or NULL for row triggers).
Why it happens
- 1A row-level trigger function returns a value of the wrong type instead of the modified row or NULL
- 2A trigger function returns a non-RECORD value from a BEFORE row trigger
- 3PL/C or external language trigger function does not comply with the Postgres trigger calling conventions
How to reproduce
Trigger function returning wrong type.
trigger — this will error
trigger — this will error
CREATE OR REPLACE FUNCTION bad_trigger() RETURNS TRIGGER AS $ BEGIN RETURN 42; -- should return NEW, OLD, or NULL END; $ LANGUAGE plpgsql;
expected output
ERROR: trigger protocol violated
Fix
Return NEW (or OLD) from BEFORE row triggers
WHEN When writing PL/pgSQL trigger functions.
Return NEW (or OLD) from BEFORE row triggers
CREATE OR REPLACE FUNCTION good_trigger() RETURNS TRIGGER AS $ BEGIN -- modify NEW as needed RETURN NEW; -- required for BEFORE triggers END; $ LANGUAGE plpgsql;
Why this works
BEFORE row triggers must return the row to be inserted/updated (NEW), the original row (OLD), or NULL to cancel the operation. Any other return type violates the protocol.
Sources
Official documentation ↗
Class 39 — External Routine Invocation Exception (Postgres-specific)
Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev