quarkusio/quarkus · error · java.lang.IllegalArgumentException

Unsupported primitive:

Error message

Unsupported primitive: 

What it means

Types.box() converts a primitive Type (byte, short, char, int, long, float, double, boolean) to its boxed wrapper class. The default branch throws IllegalArgumentException('Unsupported primitive: ...') for any Type.Kind.PRIMITIVE whose kind is not among the handled cases (e.g. VOID or unexpected primitive kinds).

Source

Thrown at extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/Types.java:214

        switch (primitive) {
            case BOOLEAN:
                return Type.create(DotNames.BOOLEAN, Kind.CLASS);
            case DOUBLE:
                return Type.create(DotNames.DOUBLE, Kind.CLASS);
            case FLOAT:
                return Type.create(DotNames.FLOAT, Kind.CLASS);
            case LONG:
                return Type.create(DotNames.LONG, Kind.CLASS);
            case INT:
                return Type.create(DotNames.INTEGER, Kind.CLASS);
            case BYTE:
                return Type.create(DotNames.BYTE, Kind.CLASS);
            case CHAR:
                return Type.create(DotNames.CHARACTER, Kind.CLASS);
            case SHORT:
                return Type.create(DotNames.SHORT, Kind.CLASS);
            default:
                throw new IllegalArgumentException("Unsupported primitive: " + primitive);
        }
    }

    static boolean isImplementorOf(ClassInfo target, DotName interfaceName, IndexView index) {
        if (target.interfaceNames().contains(interfaceName)) {
            // Direct implementor
            return true;
        }
        DotName superName = target.superName();
        if (superName != null && !superName.equals(DotName.OBJECT_NAME)) {
            ClassInfo superClass = index.getClassByName(superName);
            if (superClass != null && isImplementorOf(superClass, interfaceName, index)) {
                // Superclass is implementor
                return true;
            }
        }
        for (DotName name : target.interfaceNames()) {
            ClassInfo interfaceClass = index.getClassByName(name);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the boxed type isn't void: don't box the result of void-returning method calls
  2. If writing extension code, guard with type.kind() == Kind.PRIMITIVE && type.asPrimitiveType().primitive() != PrimitiveType.VOID before boxing
  3. File a bug with the template expression if a normal primitive (int, char, ...) triggers this

Example fix

// before
DotName boxed = Types.box(method.returnType()).name();
// after
if (method.returnType().kind() != Type.Kind.VOID) { DotName boxed = Types.box(method.returnType()).name(); }
Defensive patterns

Strategy: type-guard

Validate before calling

boolean boxable = type.kind() == Type.Kind.PRIMITIVE
    && type.asPrimitiveType().primitive() != org.jboss.jandex.PrimitiveType.VOID;

Type guard

if (type.kind() == Type.Kind.PRIMITIVE && type.asPrimitiveType().primitive() != PrimitiveType.VOID) {
    Type boxed = Types.box(type);
}

Prevention

When it happens

Trigger: Qute type-resolution code passes a primitive type to Types.box() that has no boxed mapping — typically a void method's return type or a wrongly-parsed type descriptor reaching the boxing logic.

Common situations: Template expression referencing a void-returning method where the result type is then boxed; a bug/edge case in type parsing producing an unexpected primitive kind; extension code calling Types.box directly on a void type.

Related errors


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