PostgreSQL Error 39P02: srf protocol violated
The 39P02: srf protocol violated error occurs when a Set-Returning Function (SRF) — a function designed to return multiple rows — fails to follow PostgreSQL's internal protocol for producing result sets. This typically happens in C-language extensions, procedural language functions using RETURNS SETOF, or after major version upgrades when extensions are not recompiled against the new PostgreSQL binaries.
Top 3 Causes and Fixes
1. Incorrect C-Language SRF Implementation
C-based SRFs must use the SRF_IS_FIRSTCALL(), SRF_FIRSTCALL_INIT(), SRF_PERCALL_SETUP(), SRF_RETURN_NEXT(), and SRF_RETURN_DONE() macros in the correct order. Skipping any of these — especially forgetting SRF_RETURN_DONE() — triggers the protocol violation.
Diagnosis and Quick Fix:
-- Check all C-language set-returning functions in your database
SELECT
n.nspname AS schema,
p.proname AS function_name,
p.probin AS shared_library
FROM pg_proc p
JOIN pg_namespace n ON p.pronamespace = n.oid
JOIN pg_language l ON p.prolang = l.oid
WHERE p.proretset = true
AND l.lanname = 'c'
AND n.nspname NOT IN ('pg_catalog', 'information_schema');
-- Drop and recreate the broken function after fixing the C code
DROP FUNCTION IF EXISTS broken_srf_function();
CREATE OR REPLACE FUNCTION broken_srf_function()
RETURNS SETOF TEXT
AS '/path/to/fixed_extension.so', 'broken_srf_function'
LANGUAGE C STRICT;
2. Extension Incompatibility After Major Version Upgrade
After upgrading PostgreSQL (e.g., v14 → v15), C extensions compiled against the old version can violate the SRF protocol due to ABI changes. Always recompile or reinstall extensions against the new PostgreSQL version.
-- Check installed extension versions
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE installed_version IS NOT NULL
ORDER BY name;
-- Attempt to update the extension in-place
ALTER EXTENSION your_extension_name UPDATE;
-- If update is not possible, reinstall
DROP EXTENSION IF EXISTS your_extension_name CASCADE;
-- (Install the correct OS package version first, then:)
CREATE EXTENSION your_extension_name;
-- Confirm server version to match against extension build
SELECT version();
3. Incorrect RETURNS SETOF in PL/pgSQL Functions
Using RETURN value instead of RETURN NEXT value inside a RETURNS SETOF function, or failing to call a final RETURN to signal completion, can trigger this error.
-- BAD: incorrect pattern
CREATE OR REPLACE FUNCTION bad_example()
RETURNS SETOF INTEGER
LANGUAGE plpgsql AS $$
BEGIN
RETURN 1; -- Wrong! This does not follow SRF protocol
END;
$$;
-- GOOD: correct use of RETURN NEXT
CREATE OR REPLACE FUNCTION good_example_v1()
RETURNS SETOF INTEGER
LANGUAGE plpgsql AS $$
DECLARE
i INTEGER;
BEGIN
FOR i IN 1..5 LOOP
RETURN NEXT i;
END LOOP;
RETURN; -- explicit termination
END;
$$;
-- GOOD: correct use of RETURN QUERY
CREATE OR REPLACE FUNCTION good_example_v2(p_schema TEXT)
RETURNS SETOF TEXT
LANGUAGE plpgsql AS $$
BEGIN
RETURN QUERY
SELECT tablename::TEXT
FROM pg_tables
WHERE schemaname = p_schema;
END;
$$;
-- GOOD: RETURNS TABLE pattern
CREATE OR REPLACE FUNCTION good_example_v3()
RETURNS TABLE(id INT, label TEXT)
LANGUAGE plpgsql AS $$
BEGIN
id := 1; label := 'first'; RETURN NEXT;
id := 2; label := 'second'; RETURN NEXT;
END;
$$;
-- Test the functions
SELECT * FROM good_example_v1();
SELECT * FROM good_example_v2('public');
SELECT * FROM good_example_v3();
Quick Prevention Tips
Always validate extensions before upgrading PostgreSQL.
Run pg_upgrade --check before any major version upgrade, and ensure all third-party extensions (PostGIS, TimescaleDB, etc.) have a version available for the target PostgreSQL release. Include SRF function regression tests in your CI/CD pipeline.
Prefer PL/pgSQL over C for custom SRFs when possible.
C-based SRFs are powerful but error-prone. If performance allows, implement SRFs in PL/pgSQL using RETURN NEXT or RETURN QUERY, which are far less likely to produce protocol violations. When C is necessary, strictly follow the SRF macro pattern and add unit tests that call the function in isolation.
Related Errors
-
39P01–invalid_transaction_termination: improper transaction control inside a function context. -
42P13–invalid_function_definition: malformed function definition, often a root cause of SRF issues. -
XX000–internal_error: may appear alongside39P02in server logs when a C extension crashes.
📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.
Top comments (0)