How to fix 38000: external_routine_exception in PostgreSQL
PostgreSQL raises error 38000 when an external routine (such as a C function, external procedure, or foreign data wrapper function) encounters an exception during execution. This occurs when external code linked with PostgreSQL fails, throws an exception, or violates PostgreSQL's execution environment constraints.
Quick fix
Fixes 38000
SELECT proname, prolang, prosrc
FROM pg_proc
WHERE proname LIKE '%function_name%'
AND prolang IN (SELECT oid FROM pg_language WHERE lanname IN ('c', 'plpythonu', 'plperl', etc.));- Identify the failing external routine
- Check extension and external library versions
- Debug the external routine code
- Test with simplified inputs and isolate the issue
SELECT proname, prolang, prosrcFROM pg_procWHERE proname LIKE '%function_name%'AND prolang IN (SELECT oid FROM pg_language WHERE lanname IN ('c', 'plpythonu', 'plperl', etc.));38000: external_routine_exception
What this error means
SQLSTATE 38000 belongs to class 38 (external routine exception) in PostgreSQL's error catalog. This error occurs when an external routine—such as a C-language function, external procedure, foreign data wrapper (FDW) handler, or any code running outside PostgreSQL's core—encounters an unhandled exception or failure. External routines extend PostgreSQL's functionality but run in separate execution contexts, and when they fail, PostgreSQL reports error 38000 to indicate the failure originated outside its core engine.
Typical symptoms
- Calling a C-language function or external procedure fails with 'ERROR: 38000: external_routine_exception'.
- Foreign data wrapper (FDW) operations trigger this error when the external data source or handler fails.
- Custom extensions or external libraries linked with PostgreSQL crash or throw exceptions.
- The error occurs during execution of functions marked with LANGUAGE C or other external languages.
- Database logs show stack traces pointing to external code rather than PostgreSQL core functions.
Common causes
- C-language functions (LANGUAGE C) crashing due to memory access violations, null pointer dereferences, or buffer overflows.
- External procedures or functions written in other languages (Python, Perl, etc.) throwing unhandled exceptions.
- Foreign data wrapper handlers failing to connect to external data sources or process queries correctly.
- Custom extensions with bugs in their external code implementation.
- Version mismatches between PostgreSQL and external libraries or extensions.
- Memory allocation failures or resource exhaustion in external routines.
How to fix "38000: external_routine_exception"
Examine the PostgreSQL error logs and stack trace to identify which external function is failing. Look for function names in the error message or stack trace. You can also query the system catalogs:
SELECT proname, prolang, prosrc
FROM pg_proc
WHERE proname LIKE '%function_name%'
AND prolang IN (SELECT oid FROM pg_language WHERE lanname IN ('c', 'plpythonu', 'plperl', etc.));Check for functions with LANGUAGE C or other external languages that might be causing the issue.
Verify that all extensions and external libraries are compatible with your PostgreSQL version. Check:
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE installed_version IS NOT NULL;Also check shared library dependencies:
# For Linux systems
ldd $(pg_config --pkglibdir)/*.so | grep -i "not found"Ensure all required libraries are installed and compatible.
If you have access to the source code of the failing external routine:
1. Add logging or debugging statements to identify where it fails
2. Check for memory management issues (malloc/free mismatches)
3. Validate all input parameters and boundary conditions
4. Ensure exception handling is properly implemented
For C functions, compile with debugging symbols:
gcc -g -fPIC -shared -I$(pg_config --includedir-server) -o myfunc.so myfunc.cUse tools like gdb or valgrind to debug memory issues.
Create a minimal test case to reproduce the error:
-- Test the function with simple inputs
BEGIN;
SELECT my_external_function('test_input');
ROLLBACK;Gradually add complexity to identify what triggers the failure. Check:
- Input data types and values
- Memory usage patterns
- Concurrency issues (if multiple sessions call the function)
- Resource limits (memory, file descriptors)
Enable detailed logging in the external routine if possible.
Based on your debugging results:
1. Fix the bug in the external routine code
2. Add proper error handling and validation
3. Implement resource cleanup in all code paths
4. Add input validation to prevent invalid states
If you cannot fix the external routine, consider:
- Using a different function or extension
- Implementing the logic in PL/pgSQL instead
- Creating a wrapper function with error handling
- Reporting the bug to the extension maintainer
Example wrapper function:
CREATE OR REPLACE FUNCTION safe_external_function(input text)
RETURNS text
LANGUAGE plpgsql
AS $$
BEGIN
BEGIN
RETURN external_function_that_might_fail(input);
EXCEPTION
WHEN external_routine_exception THEN
RETURN 'Error: External routine failed';
END;
END;
$$;Implement monitoring and preventive measures:
1. Add comprehensive unit tests for external routines
2. Monitor PostgreSQL logs for external routine exceptions
3. Implement circuit breakers for frequently failing external functions
4. Consider using PostgreSQL's built-in languages (PL/pgSQL) when possible
5. Regularly update extensions and external libraries
Set up alerting for external routine failures:
-- Create a function to log external routine failures
CREATE OR REPLACE FUNCTION log_external_routine_failure(
func_name text,
error_text text
) RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO external_routine_errors (function_name, error_message, occurred_at)
VALUES (func_name, error_text, NOW());
END;
$$;Advanced notes
Error 38000 represents failures in code running outside PostgreSQL's core execution engine. External routines provide powerful extension capabilities but introduce additional failure modes. C-language functions run in the same process as PostgreSQL and can crash the entire server if they have serious bugs. Foreign data wrappers and external procedures run in separate contexts but still need to handle errors gracefully. When developing external routines, comprehensive error handling, input validation, and memory management are critical. PostgreSQL's extension API provides mechanisms for memory management and error reporting that should be used consistently.
Frequently asked questions
- What does "38000" mean?
- SQLSTATE 38000 belongs to class 38 (external routine exception) in PostgreSQL's error catalog. This error occurs when an external routine—such as a C-language function, external procedure, foreign data wrapper (FDW) handler, or any code running outside PostgreSQL's core—encounters an unhandled exception or failure. External routines extend PostgreSQL's functionality but run in separate execution contexts, and when they fail, PostgreSQL reports error 38000 to indicate the failure originated outside its core engine.
- How do I fix "38000"?
- PostgreSQL raises error 38000 when an external routine (such as a C function, external procedure, or foreign data wrapper function) encounters an exception during execution. This occurs when external code linked with PostgreSQL fails, throws an exception, or violates PostgreSQL's execution environment constraints.
- What causes "38000"?
- C-language functions (LANGUAGE C) crashing due to memory access violations, null pointer dereferences, or buffer overflows. External procedures or functions written in other languages (Python, Perl, etc.) throwing unhandled exceptions. Foreign data wrapper handlers failing to connect to external data sources or process queries correctly.
- Is the "38000" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚PostgreSQL Official Documentation
- 📖PostgreSQL error codes (Class 38 includes 38000)(Official Docs)
- 📖C-language functions documentation(Official Docs)
- 📖Foreign data wrapper handler documentation(Official Docs)
- 🐙