quarkusio/quarkus · error · IllegalArgumentException

Uni must be used with type parameter

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.

Solutions

  1. Add an explicit type parameter to the Uni return type
  2. If the value is dynamic, use Uni<Object> or a concrete domain type
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/81b4abf62af68661. Report an issue: GitHub.

Appendix: 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)