quarkusio/quarkus · error · IllegalStateException

BUG: Don't know how to generate JVM bridge method for : has

Error message

BUG: Don't know how to generate JVM bridge method for : has primitive parameters

What it means

The repository Panache bytecode generator builds JVM bridge methods for generic methods. A bridge must load each parameter to forward it; primitives cannot be loaded as object references with ALOAD, so encountering Type.Kind.PRIMITIVE aborts generation with this IllegalStateException. It signals an unhandled case in the enhancement, not user misuse per se.

Source

Thrown at extensions/panache/panache-common/deployment/src/main/java/io/quarkus/panache/common/deployment/visitors/PanacheRepositoryClassOperationGenerationVisitor.java:221

        // get a bounds-erased descriptor
        String descriptor = method.descriptor();
        // make sure we need a bridge
        if (!userMethods.contains(method.name() + "/" + descriptor)) {
            MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE,
                    method.name(),
                    descriptor,
                    null,
                    null);
            List<org.jboss.jandex.Type> parameters = method.parameterTypes();
            AsmUtil.copyParameterNames(mv, method);
            mv.visitCode();
            // this
            mv.visitIntInsn(Opcodes.ALOAD, 0);
            // each param
            for (int i = 0; i < parameters.size(); i++) {
                org.jboss.jandex.Type paramType = parameters.get(i);
                if (paramType.kind() == org.jboss.jandex.Type.Kind.PRIMITIVE)
                    throw new IllegalStateException("BUG: Don't know how to generate JVM bridge method for " + method
                            + ": has primitive parameters");
                mv.visitIntInsn(Opcodes.ALOAD, i + 1);
                if (paramType.kind() == org.jboss.jandex.Type.Kind.TYPE_VARIABLE) {
                    String typeParamName = paramType.asTypeVariable().identifier();
                    Type type = typeArguments.get(typeParamName).type();
                    if (type.getSort() > Type.DOUBLE) {
                        mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
                    } else {
                        unboxIfRequired(mv, type);
                    }
                }
            }

            String targetDescriptor = method.descriptor(argMapper);
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
                    daoBinaryName,
                    method.name(),
                    targetDescriptor, false);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Box the primitive parameter (use Integer/Long/Boolean or Kotlin nullable types) so the bridge can ALOAD it.
  2. Rename the method to avoid the forced bridge against the generic supertype method.
  3. Patch generateJvmBridge to compute the correct primitive load opcode instead of throwing, and contribute upstream to Quarkus.

Example fix

// before
fun persist(f: Boolean) { ... } // collides with generic base method, needs bridge
// after
fun persist(flag: Boolean?) { ... } // boxed parameter, bridge generatable
Defensive patterns

Strategy: type-guard

Validate before calling

boolean bridgeable(org.jboss.jandex.Type[] parameters) {
    for (org.jboss.jandex.Type p : parameters)
        if (p.kind() == org.jboss.jandex.Type.Kind.PRIMITIVE) return false;
    return true;
}

Type guard

boolean hasPrimitiveParams(List<org.jboss.jandex.Type> params) {
    return params.stream().anyMatch(p -> p.kind() == org.jboss.jandex.Type.Kind.PRIMITIVE);
}

Try / catch

try {
    generateJvmBridge(method, parameters);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("primitive parameters")) {
        // box parameters or skip bridge
    } else throw e;
}

Prevention

When it happens

Trigger: visitEnd -> generateJvmBridge generates a bridge for a repository method whose parameters include a primitive (int, long, boolean, double, etc.), typically because a user method overrides a generic base method with a primitive-parameter signature.

Common situations: Kotlin/Java Panache repository implementing/overriding a generic PanacheRepositoryBase method with primitive parameters; a method whose erasure forces bridging (same name and erased signature as a type-variable method in the base class).

Related errors


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