ethereum/go-ethereum · critical

[libsecp256k1] internal consistency check failed: %s\n

Error message

[libsecp256k1] internal consistency check failed: %s\n

What it means

This is libsecp256k1's default error callback, invoked from CHECK/CHECK_BREAK internal consistency macros when an invariant inside the library itself fails (as opposed to ARG_CHECK for caller arguments). The default handler prints the message and abort()s. Seeing it means either a library bug, an ABI mismatch (e.g. struct sizes changed between the header and the linked library), or heap corruption caused by the host application.

Source

Thrown at crypto/secp256k1/libsecp256k1/src/util.h:104

typedef struct {
    void (*fn)(const char *text, void* data);
    const void* data;
} secp256k1_callback;

static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * const cb, const char * const text) {
    cb->fn(text, (void*)cb->data);
}

#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS
static void secp256k1_default_illegal_callback_fn(const char* str, void* data) {
    (void)data;
    fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
    abort();
}
static void secp256k1_default_error_callback_fn(const char* str, void* data) {
    (void)data;
    fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
    abort();
}
#else
void secp256k1_default_illegal_callback_fn(const char* str, void* data);
void secp256k1_default_error_callback_fn(const char* str, void* data);
#endif

static const secp256k1_callback default_illegal_callback = {
    secp256k1_default_illegal_callback_fn,
    NULL
};

static const secp256k1_callback default_error_callback = {
    secp256k1_default_error_callback_fn,
    NULL
};

View on GitHub (pinned to 6bb0588ad8)

Solutions

  1. Do a clean rebuild of the library and ALL code that includes its headers so layouts match
  2. Run the failing program under ASan/valgrind to catch host-side memory corruption feeding bogus state into the library
  3. Verify one single version of headers and library is on the include/link path (ldd, include order)
  4. If it reproduces with a minimal self-contained case on the latest release, report upstream with the CHECK message text

Example fix

# before
# app built against system headers, linked against local older .so
cc app.c -I/usr/include -L./build -lsecp256k1   # layout mismatch -> consistency check abort

# after
cc app.c -I./libsecp256k1/include -L./libsecp256k1/build -Wl,-rpath,./libsecp256k1/build -lsecp256k1
Defensive patterns

Strategy: validation

Validate before calling

/* Prevent the common causes before they reach the library */
_Static_assert(sizeof(secp256k1_ecdsa_signature) == 64, "ABI mismatch: rebuild all objects against the same headers");
/* and always check buffer sizes at the boundary */
if (output_len < 33) return -1;

Try / catch

/* abort() cannot be caught; contain it instead:
   - build a minimal reproducer,
   - run under ASan/valgrind to find the heap corruption,
   - crash-log (corefile/backtrace) and restart the process */

Prevention

When it happens

Trigger: Struct layout mismatch from mixing headers of one libsecp256k1 version with a shared library of another; buffer overflows in caller code corrupting secp256k1's scratch/context memory; rarely, genuine internal bugs on extreme/adversarial inputs; building with inconsistent SECP256K1_ build flags across translation units.

Common situations: Upgrading libsecp256k1 without a full rebuild of dependents (stale objects linking old struct layouts); race conditions where one thread destroys a context another still uses; FFI bindings whose struct mirroring drifted from the C source.

Related errors


AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15). Data as JSON: /api/errors/245e51bebb73fa57. Report an issue: GitHub.