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

  1. Find the exact function and argument in the printed message string (it names them, e.g. 'ctx != NULL')
  2. Check every pointer passed for NULL and every buffer size against the documented maximums before the call
  3. Ensure contexts are created with the flags required by the operations performed on them
  4. 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

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


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