java-native-access/jna · warning
JNA: error handling callback exception, continuing
Error message
JNA: error handling callback exception, continuing
What it means
After ffi_call invokes the Java callback, if a Java exception is pending and the internal handle_exception path fails (returns 0), JNA prints this message to stderr, clears/continues, and zeroes the return buffer for non-void returns. It indicates an exception escaped the Java callback AND the installed exception handler (Callback.UncaughtExceptionHandler) could not process it.
Source
Thrown at native/callback.c:481
break;
}
}
}
if (cb->rflag == CVT_STRUCTURE_BYVAL) {
resp = alloca(sizeof(jobject));
}
else if (cb->cif.rtype->size > cif->rtype->size) {
resp = alloca(cb->cif.rtype->size);
}
#define FPTR(ENV,OFFSET) (*(void **)((char *)(*(ENV)) + OFFSET))
#define JNI_FN(X) ((void (*)(void))(X))
ffi_call(&cb->java_cif, JNI_FN(FPTR(env, cb->fptr_offset)), resp, args);
if ((*env)->ExceptionCheck(env)) {
jthrowable throwable = (*env)->ExceptionOccurred(env);
(*env)->ExceptionClear(env);
if (!handle_exception(env, self, throwable)) {
fprintf(stderr, "JNA: error handling callback exception, continuing\n");
}
if (cif->rtype->type != FFI_TYPE_VOID) {
memset(oldresp, 0, cif->rtype->size);
}
}
else switch(cb->rflag) {
case CVT_INTEGER_TYPE:
if (cb->cif.rtype->size > sizeof(ffi_arg)) {
*(jlong *)oldresp = getIntegerTypeValue(env, *(void **)resp);
}
else {
*(ffi_arg *)oldresp = (ffi_arg)getIntegerTypeValue(env, *(void **)resp);
}
break;
case CVT_POINTER_TYPE:
*(void **)resp = getPointerTypeAddress(env, *(void **)resp);
break;
case CVT_NATIVE_MAPPED:View on GitHub (pinned to d036ad9781)
Solutions
- Wrap the callback body in try-catch and handle/log exceptions inside the callback itself.
- Install a robust Callback.UncaughtExceptionHandler that cannot itself throw.
- Note that the native return value is zeroed — design native callers to tolerate a zero/NULL result.
Example fix
// before
public void invoke() { doWork(); } // exception escapes to native
// after
public void invoke() {
try { doWork(); } catch (Throwable t) { log(t); }
} Defensive patterns
Strategy: try-catch
Try / catch
// Inside every callback body
public ReturnType invoke(...) {
try {
return realWork(...);
} catch (Throwable t) {
log.error("callback failed", t);
return defaultValue; // zero/NULL-equivalent
}
} Prevention
- Catch Throwable inside callback implementations; never let exceptions escape to native
- Register a Callback.UncaughtExceptionHandler that cannot itself throw
- Ensure native callers tolerate zeroed return values when a callback fails
When it happens
Trigger: The Java callback method throws, and the registered UncaughtExceptionHandler itself throws, or none is installed and the default handling fails, when native code invokes the callback via ffi_call.
Common situations: Callbacks that throw unexpected runtime exceptions (NPE, etc.) while native code holds no Java exception expectations; misconfigured Callback.UncaughtExceptionHandler that itself errors.
Related errors
- JNA: callback object has been garbage collected
- JNA: Unhandled arg conversion type %d
- JNA: Likely memory leak here
- Win32Exception(rc)
- Win32Exception(Kernel32.INSTANCE.GetLastError())
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/cc18d24f968fd7f1.
Report an issue: GitHub.