quarkusio/quarkus · error · RuntimeException

Invalid proxy passed to recorder. Parameter ${i} of type ${m

Error message

Invalid proxy passed to recorder. Parameter ${i} of type ${method.getParameterTypes()[i]} was created in a runtime recorder method, while this recorder is for a static init method. The object will not have been created at the time this method is run.

What it means

Quarkus recorders run in two phases: STATIC_INIT (build/init time) and RUNTIME_INIT. Objects returned by runtime recorder methods exist only as runtime proxies. When a static-init recorder method receives such a proxy as a parameter, the value cannot exist yet at static-init time, so BytecodeRecorderImpl.invoke() rejects the call rather than recording a reference to a non-existent object.

Source

Thrown at core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java:335

        return true;
    }

    public <T> T getRecordingProxy(Class<T> theClass) {
        if (existingProxyClasses.containsKey(theClass)) {
            return theClass.cast(existingProxyClasses.get(theClass));
        }
        NewRecorder newRecorder = new NewRecorder(theClass);
        existingRecorderValues.put(theClass, newRecorder);

        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (staticInit) {
                    for (int i = 0; i < args.length; ++i) {
                        if (args[i] instanceof ReturnedProxy) {
                            ReturnedProxy p = (ReturnedProxy) args[i];
                            if (!p.__static$$init()) {
                                throw new RuntimeException("Invalid proxy passed to recorder. Parameter " + i + " of type "
                                        + method.getParameterTypes()[i]
                                        + " was created in a runtime recorder method, while this recorder is for a static init method. The object will not have been created at the time this method is run.");
                            }
                        }
                    }
                }
                StoredMethodCall storedMethodCall = new StoredMethodCall(theClass, method, args);
                storedMethodCalls.add(storedMethodCall);
                Class<?> returnType = method.getReturnType();
                if (method.getName().equals("toString")
                        && method.getParameterCount() == 0
                        && returnType.equals(String.class)) {
                    return proxy.getClass().getName();
                }

                boolean voidMethod = method.getReturnType().equals(void.class);
                if (!voidMethod && !isProxiable(method.getReturnType())) {
                    throw new RuntimeException("Cannot use " + method

View on GitHub (pinned to e1c734241f)

Solutions

  1. Move the consuming recorder call to RUNTIME_INIT so the proxy exists at that phase
  2. Split logic: record static-init part without runtime proxies, do runtime-dependent work in a runtime-init recorder
  3. Ensure the producer recorder method is also static-init so its proxy is marked __static$$init
  4. Check recorder @Recorder constructors/annotations to align phases of producer and consumer

Example fix

// before
RecorderBeanStaticInit.recorder.configure(runtimeRecorder.getValue()); // static init, runtime proxy param
// after
@Recorder(ExecutionTime.RUNTIME_INIT)
public class RecorderBeanRuntime { void configure(MyValue v) { ... } }
Defensive patterns

Strategy: validation

Validate before calling

if (proxy instanceof ReturnedProxy rp && !rp.__static$$init() && targetRecorderIsStaticInit) {
    throw new IllegalStateException("runtime proxy passed to static init recorder");
}

Prevention

When it happens

Trigger: Calling a recorder method registered for static init (RUNTIME_INIT absent / staticInit=true) and passing as an argument the return value (a ReturnedProxy) of a RUNTIME_INIT recorder method or RuntimeValue from a runtime init context.

Common situations: Mixing recorder phases in a build step: consuming a RUNTIME_INIT build item's recorder result inside a STATIC_INIT recorder call; forgetting @Recoder(..., SetupEvent) phase annotations; passing RuntimeValue contents across phases.

Related errors


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