quarkusio/quarkus · error · RuntimeException

Failed to convert method argument '%s' to Permission constru

Error message

Failed to convert method argument '%s' to Permission constructor parameter

What it means

convertMethodParamToPermParam() invokes the registered parameter converter MethodHandle on a secured method argument when constructing a Permission for @PermissionsAllowed. Any Throwable raised by the converter (ClassCastException, NPE, business-logic failure) is wrapped in a RuntimeException identifying which argument failed conversion.

Source

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

            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);
        }
    }

    public Function<SyntheticCreationalContext<QuarkusPermissionSecurityIdentityAugmentor>, QuarkusPermissionSecurityIdentityAugmentor> createPermissionAugmentor() {
        return new Function<SyntheticCreationalContext<QuarkusPermissionSecurityIdentityAugmentor>, QuarkusPermissionSecurityIdentityAugmentor>() {
            @Override
            public QuarkusPermissionSecurityIdentityAugmentor apply(
                    SyntheticCreationalContext<QuarkusPermissionSecurityIdentityAugmentor> ctx) {
                return new QuarkusPermissionSecurityIdentityAugmentor(ctx.getInjectedReference(BlockingSecurityExecutor.class));
            }
        };
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Read the nested cause (e) in the stack trace to see the converter's actual failure.
  2. Make the converter null-safe and use instanceof checks/casting that tolerate the actual argument types.
  3. Validate or normalize the method argument at the call site before invoking the secured method.
  4. Change the converter to String.valueOf(...) or equivalent rather than a hard cast.

Example fix

// before
public static Object convert(Object arg) { return (String) arg; }
// after
public static Object convert(Object arg) { return arg == null ? null : arg.toString(); }
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-validate arguments before calling the secured method
if (arg == null || !(arg instanceof String)) {
    throw new IllegalArgumentException("Argument not convertible to permission parameter");
}

Try / catch

try {
    return converter.invokeExact(methodArg);
} catch (ClassCastException e) {
    throw new IllegalStateException("Converter received unexpected argument type: " + methodArg.getClass(), e);
} catch (Throwable e) {
    throw new IllegalStateException("Parameter conversion failed", e);
}

Prevention

When it happens

Trigger: Invoking a @PermissionsAllowed-annotated method whose argument fails the converter method (e.g. converter does an unchecked cast to a type the actual argument does not match, or the argument is null).

Common situations: Runtime argument type differs from the type the converter assumes (e.g. Integer passed where converter casts to String); caller passes null and the converter dereferences it; converter logic throws for specific input values.

Related errors


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