quarkusio/quarkus · error · RuntimeException

Failed to create Permission constructor method parameter con

Error message

Failed to create Permission constructor method parameter converter

What it means

createPermissionMethodConverter() looks up a static method (named by methodName) on the given class via MethodHandles.publicLookup(), expecting signature Object -> Object, to convert @PermissionsAllowed method arguments into Permission constructor parameters. If no such accessible static method exists (or it is not accessible to a public lookup), a RuntimeException is thrown at build/startup time.

Source

Thrown at extensions/security/runtime/src/main/java/io/quarkus/security/runtime/SecurityCheckRecorder.java:420

        runtimeConfigReady = true;
    }

    public void unsetRuntimeConfigReady(ShutdownContext shutdownContext) {
        shutdownContext.addShutdownTask(new Runnable() {
            @Override
            public void run() {
                runtimeConfigReady = false;
            }
        });
    }

    public RuntimeValue<MethodHandle> createPermissionMethodConverter(String methodName, RuntimeValue<Class<?>> clazz) {
        try {
            var handle = MethodHandles.publicLookup().findStatic(clazz.getValue(), methodName,
                    MethodType.methodType(Object.class, Object.class));
            return new RuntimeValue<>(handle);
        } catch (NoSuchMethodException | IllegalAccessException e) {
            throw new RuntimeException("Failed to create Permission constructor method parameter converter", e);
        }
    }

    public RuntimeValue<Class<?>> loadClassRuntimeVal(String className) {
        return new RuntimeValue<>(loadClass(className));
    }

    private static Object convertMethodParamToPermParam(int i, Object methodArg,
            Map<String, RuntimeValue<MethodHandle>> converterNameToMethodHandle, String[] formalParamConverters) {
        var converter = converterNameToMethodHandle.get(formalParamConverters[i]).getValue();
        try {
            return converter.invokeExact(methodArg);
        } catch (Throwable e) {
            throw new RuntimeException(
                    "Failed to convert method argument '%s' to Permission constructor parameter".formatted(methodArg), e);
        }
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the converter method public and static, with signature taking exactly one parameter and returning a value.
  2. Verify the method name passed in the annotation/configuration matches exactly.
  3. Ensure the converter method is visible to a public lookup (public class, public method — not in a private nested class).
  4. Change the method to accept and return the types compatible with the permission constructor parameter.

Example fix

// before
private String normalize(String arg) { return arg.toLowerCase(); }
// after
public static Object normalize(Object arg) { return ((String) arg).toLowerCase(); }
Defensive patterns

Strategy: validation

Validate before calling

// before configuring the converter, verify lookup works
MethodHandles.publicLookup().findStatic(ConverterClass.class, "normalize",
    MethodType.methodType(Object.class, Object.class));

Try / catch

try {
    var handle = MethodHandles.publicLookup().findStatic(clazz, methodName,
        MethodType.methodType(Object.class, Object.class));
} catch (NoSuchMethodException | IllegalAccessException e) {
    throw new IllegalStateException("Converter must be public static Object m(Object)", e);
}

Prevention

When it happens

Trigger: Using a converter name in @PermissionsAllowed (e.g. @PermissionsAllowed(value="...", converter="myConverter")) where the referenced class has no public static method with that name taking one Object parameter and returning Object.

Common situations: Converter method is instance (non-static); method is private or package-private (publicLookup cannot see it); method has a different arity; typo in method name; converter declared on the wrong class.

Related errors


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