apache/kafka · error · IllegalArgumentException
The argument to complete can not be an instance of RuntimeEx
Error message
The argument to complete can not be an instance of RuntimeException
What it means
Thrown by RequestFuture.complete(T value) when the value passed in is itself a RuntimeException. The future uses result instanceof RuntimeException internally to distinguish failure from success (see failed()), so accepting a RuntimeException as a success value would corrupt that invariant and make succeeded()/failed() report contradictory state. Callers must signal failure through raise(RuntimeException), not complete().
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/RequestFuture.java:125
* @throws IllegalStateException if the future is not complete or completed successfully
*/
public RuntimeException exception() {
if (!failed())
throw new IllegalStateException("Attempt to retrieve exception from future which hasn't failed");
return (RuntimeException) result.get();
}
/**
* Complete the request successfully. After this call, {@link #succeeded()} will return true
* and the value can be obtained through {@link #value()}.
* @param value corresponding value (or null if there is none)
* @throws IllegalStateException if the future has already been completed
* @throws IllegalArgumentException if the argument is an instance of {@link RuntimeException}
*/
public void complete(T value) {
try {
if (value instanceof RuntimeException)
throw new IllegalArgumentException("The argument to complete can not be an instance of RuntimeException");
if (!result.compareAndSet(INCOMPLETE_SENTINEL, value))
throw new IllegalStateException("Invalid attempt to complete a request future which is already complete");
fireSuccess();
} finally {
completedLatch.countDown();
}
}
/**
* Raise an exception. The request will be marked as failed, and the caller can either
* handle the exception or throw it.
* @param e corresponding exception to be passed to caller
* @throws IllegalStateException if the future has already been completed
*/
public void raise(RuntimeException e) {
try {
if (e == null)View on GitHub (pinned to c31c9215e1)
Solutions
- Route exception payloads through future.raise(e) (or RequestFuture.failure(e)) and reserve complete() for real success values.
- If you are writing a generic adapter, branch on instanceof RuntimeException before deciding complete() vs raise().
- Check the static type of T; if T can be a RuntimeException, narrow the type so success and failure paths are disjoint.
Example fix
// before
RequestFuture<RuntimeException> f = ...;
f.complete(maybeAnException); // throws if value is RuntimeException
// after
if (value instanceof RuntimeException) {
future.raise((RuntimeException) value);
} else {
future.complete(value);
} Defensive patterns
Strategy: type-guard
Validate before calling
// Before calling complete(value), ensure value is not a RuntimeException.
if (value instanceof RuntimeException) {
// use raise((RuntimeException) value) instead, which is the correct API
future.raise((RuntimeException) value);
} else {
future.complete(value);
} Type guard
// Guard that rejects RuntimeException payloads at compile-friendly boundary.
java.util.function.BiConsumer<RequestFuture<Object>, Object> safeComplete = (f, v) -> {
if (v instanceof RuntimeException) {
throw new IllegalArgumentException(
"Use RequestFuture.raise() for failures, not complete()");
}
f.complete(v);
}; Try / catch
try {
future.complete(value);
} catch (IllegalArgumentException ex) {
// value was a RuntimeException; route it through raise() instead
if (value instanceof RuntimeException) {
future.raise((RuntimeException) value);
}
} Prevention
- Reserve complete() for success payloads and raise() for failures — never mix them.
- Avoid Object-typed value variables flowing into complete(); keep success and failure types distinct.
- Remember that RequestFuture uses RuntimeException internally to mark the failed state, so a RuntimeException payload is ambiguous by design.
When it happens
Trigger: Calling future.complete(someRuntimeException); generic adapters that forward an arbitrary payload of type T where T is or extends RuntimeException; reflection or generified helper code that passes the wrong object into complete().
Common situations: Refactoring a pipeline so an exception object flows into a code path that calls complete() instead of raise(); custom RequestFutureAdapter implementations whose onSuccess wraps exceptions; passing a kafka Errors.exception() result into complete() by mistake.
Related errors
- Attempt to retrieve exception from future which hasn't faile
- Invalid attempt to complete a request future which is alread
- The exception passed to raise must not be null
- Not authorized to access topics: ${unauthorizedTopics}
- Topic '${topic}' is invalid
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/9b23fae8923a5b54.json.
Report an issue: GitHub.