{"record":{"id":"b4636c48688197e9","repo":"quarkusio/quarkus","slug":"invalid-proxy-passed-to-recorder-parameter-i-o","errorCode":null,"errorMessage":"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.","messagePattern":"Invalid proxy passed to recorder\\. Parameter (.+?) of type (.+?) 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\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java","lineNumber":335,"sourceCode":"        return true;\n    }\n\n    public <T> T getRecordingProxy(Class<T> theClass) {\n        if (existingProxyClasses.containsKey(theClass)) {\n            return theClass.cast(existingProxyClasses.get(theClass));\n        }\n        NewRecorder newRecorder = new NewRecorder(theClass);\n        existingRecorderValues.put(theClass, newRecorder);\n\n        InvocationHandler invocationHandler = new InvocationHandler() {\n            @Override\n            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n                if (staticInit) {\n                    for (int i = 0; i < args.length; ++i) {\n                        if (args[i] instanceof ReturnedProxy) {\n                            ReturnedProxy p = (ReturnedProxy) args[i];\n                            if (!p.__static$$init()) {\n                                throw new RuntimeException(\"Invalid proxy passed to recorder. Parameter \" + i + \" of type \"\n                                        + method.getParameterTypes()[i]\n                                        + \" 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.\");\n                            }\n                        }\n                    }\n                }\n                StoredMethodCall storedMethodCall = new StoredMethodCall(theClass, method, args);\n                storedMethodCalls.add(storedMethodCall);\n                Class<?> returnType = method.getReturnType();\n                if (method.getName().equals(\"toString\")\n                        && method.getParameterCount() == 0\n                        && returnType.equals(String.class)) {\n                    return proxy.getClass().getName();\n                }\n\n                boolean voidMethod = method.getReturnType().equals(void.class);\n                if (!voidMethod && !isProxiable(method.getReturnType())) {\n                    throw new RuntimeException(\"Cannot use \" + method","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java#L317-L353","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Move the consuming recorder call to RUNTIME_INIT so the proxy exists at that phase","Split logic: record static-init part without runtime proxies, do runtime-dependent work in a runtime-init recorder","Ensure the producer recorder method is also static-init so its proxy is marked __static$$init","Check recorder @Recorder constructors/annotations to align phases of producer and consumer"],"exampleFix":"// before\nRecorderBeanStaticInit.recorder.configure(runtimeRecorder.getValue()); // static init, runtime proxy param\n// after\n@Recorder(ExecutionTime.RUNTIME_INIT)\npublic class RecorderBeanRuntime { void configure(MyValue v) { ... } }","handlingStrategy":"validation","validationCode":"if (proxy instanceof ReturnedProxy rp && !rp.__static$$init() && targetRecorderIsStaticInit) {\n    throw new IllegalStateException(\"runtime proxy passed to static init recorder\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Match recorder ExecutionTime between producer and consumer","Never pass RUNTIME_INIT results into STATIC_INIT recorder calls","Review build step ordering: static-init recorders consume only static-init values"],"tags":["recorder","static-init","runtime-init","build-time"],"backgroundTag":"recorder-phase-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}