quarkusio/quarkus · error · IllegalArgumentException
Uni must be used with type parameter (e.g. Uni<String>).
Error message
Uni must be used with type parameter (e.g. Uni<String>).
What it means
Funqy supports reactive functions returning Mutiny Uni. The FunctionInvoker constructor inspects the generic return type to determine the output type. A raw Uni (no type parameter, e.g. method returns plain Uni) gives no output type, so an IllegalArgumentException is thrown at startup.
Source
Thrown at extensions/funqy/funqy-server-common/runtime/src/main/java/io/quarkus/funqy/runtime/FunctionInvoker.java:57
}
parameterInjectors.add(injector);
}
}
constructor = new FunctionConstructor(targetClass);
Class<?> returnType = method.getReturnType();
if (returnType != null) {
if (Uni.class.isAssignableFrom(returnType)) {
outputType = null;
isAsync = true;
Type genericReturnType = method.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType) {
Type[] actualParams = ((ParameterizedType) genericReturnType).getActualTypeArguments();
if (actualParams.length == 1) {
outputType = actualParams[0];
}
}
if (outputType == null) {
throw new IllegalArgumentException(
"Uni must be used with type parameter (e.g. Uni<String>).");
}
} else {
outputType = method.getGenericReturnType();
}
}
}
/**
* Allow storage of binding specific objects that are specific to the function.
* i.e. json marshallers
*
* @return
*/
public Map<String, Object> getBindingContext() {
return bindingContext;
}
View on GitHub (pinned to e1c734241f)
Solutions
- Add an explicit type parameter to the Uni return type
- If the value is dynamic, use Uni<Object> or a concrete domain type
- Rebuild; the check runs when the invoker is constructed at startup
Example fix
// before
@Funq public Uni getData() { ... }
// after
@Funq public Uni<String> getData() { ... } Defensive patterns
Strategy: type-guard
Validate before calling
// Verify Uni return types are parameterized before startup
static void assertParameterizedUni(Method m) {
Type rt = m.getGenericReturnType();
if (rt instanceof Class && Uni.class.isAssignableFrom((Class<?>) rt))
throw new IllegalArgumentException(m + " must return Uni<T> with a type parameter");
} Type guard
static boolean isParameterizedUni(Type returnType) {
return returnType instanceof ParameterizedType
&& ((ParameterizedType) returnType).getRawType() == Uni.class;
} Try / catch
try {
registry.register(...);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Uni must be used with type parameter"))
log.errorf("Fix return type to Uni<T>, method: %s", e.getMessage());
throw e;
} Prevention
- Never return raw Uni in @Funq methods
- Let the compiler infer generics instead of casting to raw Uni
- Add a reflection-based startup test asserting all @Funq returns are parameterized
- Prefer concrete domain types over Uni<Object>
When it happens
Trigger: Declaring @Funq public Uni noTypeParam() { ... } — returning Uni without a generic parameter such as Uni<String>.
Common situations: Writing a reactive function quickly and forgetting the generic; IDEs generating raw Uni when refactoring from CompletionStage; type erasure surprises when returning Uni.fromFuture(...).
Related errors
- Illegal key type for map
- Cannot get QueryReader for: " + type
- A generic type is not allowed here; try creating a subclass
- Unsupported wildcard type: ${wildcard}
- Can not add converter ${converter.name()} that is not parame
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/81b4abf62af68661.
Report an issue: GitHub.