PostgreSQL Unterminated C String (SQLSTATE 22024)

PostgreSQL raises ERROR: unterminated C string with SQLSTATE 22024 and condition name unterminated_c_string when a C-style (null-terminated) string passed to or returned by an internal PostgreSQL function is missing its terminating null byte. This error belongs to error class 22 (Data Exception).

What This Error Means

SQLSTATE class 22 covers data exceptions — errors that occur when the actual data values being processed violate expectations, rather than structural or permission problems. Within that class, 22024 specifically signals that PostgreSQL encountered a C string that does not end with the required null byte (\0).

PostgreSQL's internal C code, as well as C-language extension functions loaded via CREATE FUNCTION ... LANGUAGE C, work with null-terminated strings natively. When a string argument reaches an internal function that expects a C string, PostgreSQL verifies it can be safely treated as one. If the string data is malformed — for instance, because it was constructed by a buggy extension, passed through a low-level binary interface, or copied from corrupted storage — and the null terminator is absent, PostgreSQL raises 22024 rather than read beyond the allocated buffer.

After this error occurs the current transaction is aborted. Any subsequent statements in the same transaction will fail with ERROR: current transaction is aborted, commands ignored until end of transaction block until you issue a ROLLBACK (or ROLLBACK TO SAVEPOINT). The server process itself is unaffected; only the session's current transaction is rolled back.

Common Causes

  1. Buggy C-language extension functions. A custom extension written in C that constructs or returns a char * without appending \0 will trigger this error when PostgreSQL's input/output infrastructure processes the string. This is the most common real-world cause.

  2. Corrupted data in bytea or text columns passed to internal functions. Calling a function that internally converts a bytea value to a C string (for example, certain regex or encoding functions) with data that lacks a null terminator can reproduce this error.

  3. Direct use of server-internal functions with crafted binary input. Functions exposed via pg_catalog that accept cstring pseudo-type arguments (such as type input functions) expect a genuine null-terminated string. Passing raw bytes through psql \lo_* commands or via libpq binary protocol in a way that omits the null byte will raise 22024.

  4. Extension or foreign data wrapper (FDW) bugs. An FDW or background worker that builds string arguments for PostgreSQL internal APIs without proper null termination can surface this error in production, often intermittently depending on heap layout.

How to Fix unterminated_c_string

  1. If caused by a third-party or custom extension, update or patch it. The fix belongs in the C code that builds the string. Every char * handed to a PostgreSQL internal function must end with \0. The canonical pattern in extension code is:

    /* Correct: allocate one extra byte and terminate */
    char *buf = palloc(len + 1);
    memcpy(buf, src, len);
    buf[len] = '\0';
    

    If you cannot modify the extension, check whether a newer version fixes the bug and upgrade.

  2. Reproduce with a minimal test case and isolate the bad input. If the error appears on specific rows, identify which value triggers it:

    -- Test whether a specific column value causes the error
    SELECT your_function(col) FROM your_table WHERE id = <suspect_id>;
    

    Narrow down the problematic row, then decide whether to clean the data or skip the row.

  3. Validate binary data before passing it to string-expecting functions. If you are working with bytea columns and converting them to text, ensure the byte sequence ends with \x00 where required:

    -- Check if a bytea value ends with a null byte
    SELECT octet_length(your_bytea_col),
           right(your_bytea_col::text, 4)
    FROM   your_table
    WHERE  id = <suspect_id>;
    
  4. Wrap risky calls in a savepoint to limit transaction damage. When you expect possible 22024 errors during batch processing, use savepoints so only the failing statement is rolled back:

    BEGIN;
    SAVEPOINT sp1;
    SELECT your_function(col) FROM your_table;
    -- If error occurs:
    ROLLBACK TO SAVEPOINT sp1;
    -- Continue processing other rows
    COMMIT;
    
  5. For cstring-accepting internal functions, never bypass the text/varchar layer. Prefer passing values as text or varchar and letting PostgreSQL's type system handle the conversion rather than calling cstring-typed functions directly.

Additional Information

  • SQLSTATE 22024 is defined in the SQL standard as well as in PostgreSQL. It has been present in PostgreSQL across all supported versions; there is no version-specific behavior change to note.
  • Related SQLSTATE codes in class 22 include: 22000 (data exception), 22001 (string data right truncation), 22003 (numeric value out of range), 22007 (invalid datetime format), 22P02 (invalid text representation), and 22021 (character not in repertoire).
  • Client drivers such as libpq, psycopg2, asyncpg, and JDBC all surface this as a DataException (or equivalent) with sqlstate = "22024". Check the pgcode attribute in psycopg2 or the getSQLState() method in JDBC to distinguish it from other data exceptions.
  • This error is rare in plain SQL workloads. It almost always points to a C-level bug in an extension, FDW, or background worker rather than to user data or SQL logic. If you see it without any custom extensions loaded, check for PostgreSQL bugs in your version and consider filing a bug report.

Frequently Asked Questions

Why does this error say "C string" — I'm not writing C code? PostgreSQL's internal runtime is written in C, and many type input/output functions and extensions use C-style null-terminated strings internally. Even when you write plain SQL, the values you pass may be handled by C functions under the hood. SQLSTATE 22024 surfaces when one of those internal C functions receives data that does not conform to the null-termination contract expected by C strings.

Can corrupted PostgreSQL storage cause this error? In theory, badly corrupted heap pages could cause a C string to lose its null terminator, but this is extremely unlikely in practice. The far more common cause is a buggy extension or FDW. If you suspect storage corruption, run VACUUM and check the PostgreSQL logs for other signs of corruption such as checksum failures or invalid page messages.

My query worked fine for months and now raises 22024 — what changed? The most likely culprit is an extension or FDW upgrade (or downgrade) that introduced a bug in string handling, or new data that exercises a previously untested code path in an existing extension. Check whether any extensions were updated around the time the error started appearing, and review the extension's changelog for C-string-related fixes.

Is this a security vulnerability? In PostgreSQL itself the error is a safe defensive check — the server raises the exception rather than reading past the buffer, so it does not lead to a buffer overread in the server process. However, the root cause (a missing null terminator in extension code) could be a sign of a broader memory-safety issue in that extension. Audit the extension's C code if you own it.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.