ethereum/go-ethereum · critical
[libsecp256k1] illegal argument: %s\n
Error message
[libsecp256k1] illegal argument: %s\n
What it means
This is libsecp256k1's default illegal-argument callback: internal ARG_CHECK macros invoke it when an API is called with a NULL pointer, a non-canonical input, or an argument violating preconditions. The default implementation prints the message and calls abort(), killing the process — by design, because calling conventions were violated. Hosts can override it by defining USE_EXTERNAL_DEFAULT_CALLBACKS and installing their own callbacks.
Source
Thrown at crypto/secp256k1/libsecp256k1/src/util.h:99
break; \
default: ; \
} \
stmt; \
} while(0)
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 = {View on GitHub (pinned to 6bb0588ad8)
Solutions
- Find the exact function and argument in the printed message string (it names them, e.g. 'ctx != NULL')
- Check every pointer passed for NULL and every buffer size against the documented maximums before the call
- Ensure contexts are created with the flags required by the operations performed on them
- In embedded/production hosts, build with USE_EXTERNAL_DEFAULT_CALLBACKS and install a callback that maps to your error handling instead of abort
Example fix
// before secp256k1_ecdsa_signature_parse_compact(NULL, &sig, in72); // ctx NULL -> abort // after if (ctx == NULL || in72 == NULL) return ERR_INVALID_ARG; if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, in72)) return ERR_PARSE;
Defensive patterns
Strategy: validation
Validate before calling
/* guard every call site's preconditions */
if (ctx == NULL || pubkey == NULL || sig == NULL) {
return -1; /* caller error, no abort */
}
int ok = secp256k1_ecdsa_verify(ctx, sig, msg32, pubkey);
if (!ok) { /* invalid signature, not a crash */ } Type guard
static int sane_ctx(const secp256k1_context *ctx, unsigned need_flags) {
return ctx != NULL && (ctx->declassify_flags_dummy, 1); /* plus flag checks per API docs */
} Try / catch
/* Not catchable in C (abort). If hosting in another process, sandbox the crypto call:
run signing in a supervised child so an abort becomes a restartable failure. */
#ifdef USE_EXTERNAL_DEFAULT_CALLBACKS
void secp256k1_default_illegal_callback_fn(const char *str, void *d) {
host_report_illegal(str); /* log + longjmp/exception at the embedding layer */
}
#endif Prevention
- Check every pointer and return value before calling secp256k1 APIs
- Create contexts with all flags your operations require
- Build embedders with USE_EXTERNAL_DEFAULT_CALLBACKS to convert aborts into reportable errors
When it happens
Trigger: Passing NULL context/key/signature to any secp256k1 function; using a context created without the required SECP256K1_CONTEXT_* flags for that operation (e.g. signing with a VERIFY-only context in older API versions); passing overflow-length size_t arguments that trigger checked macros.
Common situations: Go bindings copying into undersized buffers; forgetting to check the return of secp256k1_ecdsa_pubkey_create before using the output; upgrading libsecp256k1 where previously-lenient NULL handling became ARG_CHECK'd; memory corruption from the surrounding application.
Related errors
- [libsecp256k1] internal consistency check failed: %s\n
- ./bench: unrecognized argument.\n\n
- ./bench: ECDH module not enabled.\n
- ./bench: Public key recovery module not enabled.\n
- ./bench: Schnorr signatures module not enabled.\n
AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15).
Data as JSON: /api/errors/76746654604b8e51.
Report an issue: GitHub.