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
  1. 1A row-level trigger function returns a value of the wrong type instead of the modified row or NULL
  2. 2A trigger function returns a non-RECORD value from a BEFORE row trigger
  3. 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

← All PostgreSQL errors