XX000
PostgreSQLERRORCriticalInternal ErrorLOW confidence

internal error

Production Risk

XX000 on a critical code path can make an entire table or database unreadable. If it accompanies WAL replay errors it may indicate corruption requiring point-in-time recovery from a clean backup. Treat any XX000 in production as a Tier 3 incident until the root cause is established.

What this means

Postgres encountered an unexpected internal condition that it does not have a more specific error code for. This is typically a Postgres bug, a data corruption condition, or an extension or custom function triggering an unexpected code path.

Why it happens
  1. 1A Postgres bug triggered by a specific query pattern or data combination
  2. 2Data file corruption causing the executor to encounter unexpected data
  3. 3A buggy extension or procedural language function calling internal APIs incorrectly
  4. 4Assert failure in a debug build of Postgres
  5. 5Inconsistent catalog state after an incomplete upgrade or manual catalog modification
How to reproduce

An internal assertion or unexpected code path is hit during query execution.

trigger — this will error
trigger — this will error
-- XX000 cannot be reliably triggered by a safe SQL statement.
-- Diagnostics: check the server log for the preceding CONTEXT and DETAIL lines.
SELECT pg_current_logfile(); -- find the current log file path

expected output

ERROR:  internal error
-- Accompanied in server logs by:
-- CONTEXT: ... (stack trace or function name)
-- DETAIL: ... (additional detail)

Fix 1

Check server logs and report the bug

WHEN Always — XX000 requires investigation of the server log for the full context.

Check server logs and report the bug
-- Find the log file:
SELECT pg_current_logfile();

-- Check recent errors in pg_log (if log_destination includes csvlog):
SELECT log_time, error_severity, message, detail, context
FROM pg_read_file(current_setting('log_directory') || '/...')
-- (read the log file outside SQL for full context)

-- Check for data corruption:
SELECT * FROM pg_catalog.pg_class WHERE relname = 'suspected_table';

Why this works

XX000 is raised by elog(ERROR, ...) calls in Postgres source code that do not map to a specific SQLSTATE. The server log contains CONTEXT lines with the C function and source location, which is essential for bug reporting. Filing a bug at bugs.postgresql.org with the full log excerpt and a minimal reproducer enables core developers to fix the issue.

Fix 2

Run pg_dump and restore to repair catalog inconsistencies

WHEN When XX000 is triggered consistently by accessing a specific table or view and corruption is suspected.

Run pg_dump and restore to repair catalog inconsistencies
-- Dump the affected database:
-- pg_dump mydb > mydb_backup.sql

-- Check table integrity:
SELECT * FROM pg_catalog.pg_class WHERE oid = 'suspect_table'::regclass;

-- Run VACUUM FULL to rewrite the heap:
VACUUM FULL suspect_table;

Why this works

pg_dump reads data through the Postgres type system and will fail loudly on corrupt data. VACUUM FULL rewrites the heap file, which can resolve minor page-level inconsistencies. Logical dump + restore to a new database is the canonical method for recovering from catalog corruption.

What not to do

Ignore recurring XX000 errors in production

XX000 on a specific query pattern often indicates a real bug or corruption that will worsen; report and investigate every occurrence.

Sources
Official documentation ↗

src/include/utils/elog.h — elog(ERROR, ...)

Reporting Bugs

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All PostgreSQL errors