{"record":{"id":"7394cb2c7e70705e","repo":"quarkusio/quarkus","slug":"invalid-proxy-passed-to-recorder-rp-was-create","errorCode":null,"errorMessage":"Invalid proxy passed to recorder. ${rp} 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\\. (.+?) 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":735,"sourceCode":"                    return value;\n                }\n            };\n        } else if (param instanceof Enum) {\n            Enum e = (Enum) param;\n            return new DeferredParameter() {\n                @Override\n                ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHandle array) {\n                    ResultHandle nm = method.load(e.name());\n                    return method.invokeStaticMethod(\n                            ofMethod(e.getDeclaringClass(), \"valueOf\", e.getDeclaringClass(), String.class),\n                            nm);\n                }\n            };\n        } else if (param instanceof ReturnedProxy) {\n            //if this is a proxy we just grab the value from the StartupContext\n            ReturnedProxy rp = (ReturnedProxy) param;\n            if (!rp.__static$$init() && staticInit) {\n                throw new RuntimeException(\"Invalid proxy passed to recorder. \" + rp\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            String proxyId = rp.__returned$proxy$key();\n            //because this is the result of a method invocation that may not have happened at param deserialization time\n            //we just load it from the startup context\n            return new DeferredParameter() {\n                @Override\n                ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHandle array) {\n                    return method.invokeVirtualMethod(ofMethod(StartupContext.class, \"getValue\", Object.class, String.class),\n                            method.getMethodParam(0), method.load(proxyId));\n                }\n            };\n        } else if (param instanceof Duration) {\n            return new DeferredParameter() {\n                @Override\n                ResultHandle doLoad(MethodContext context, MethodCreator method, ResultHandle array) {\n                    return method.invokeStaticMethod(ofMethod(Duration.class, \"parse\", Duration.class, CharSequence.class),\n                            method.load(param.toString()));","sourceCodeStart":717,"sourceCodeEnd":753,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java#L717-L753","documentation":"Recorder objects returned by runtime-recorder methods are stored in the StartupContext and only exist when runtime init runs. A recorder executing in STATIC_INIT runs before that, so passing such a proxy into a static-init recorder would reference an object that does not exist yet. Quarkus detects this via the proxy's __static$$init flag and fails the build with this message.","triggerScenarios":"In a @Recorder(Phase.STATIC_INIT) recorder method, a parameter is a proxy returned from another recorder that ran in Phase.RUNTIME_INIT (e.g. a RuntimeValue<BeanContainer> or proxy from a runtime-init record method).","commonSituations":"Extension developers wiring runtime-init results (CDI bean containers, HTTP handlers, clients created at runtime) into static-init recorders; copying recorder code between phases without adjusting the phase; upstream extension changing a recorder's phase.","solutions":["Change the consuming recorder to @Record(ExecutionTime.RUNTIME_INIT) so it runs when the proxy exists","Obtain the value at STATIC_INIT time instead: call the producer recorder method in a STATIC_INIT @Record context","Restructure so the static-init recorder only receives build-time-serializable values, and the runtime value is consumed in a runtime recorder","Check the producer recorder's phase — a value you assume is static-init may come from RUNTIME_INIT","If using RuntimeValue, ensure the underlying recorder method was recorded in the same phase as the consumer"],"exampleFix":"// before\n@Record(ExecutionTime.STATIC_INIT)\nvoid init(MyRecorder r, RuntimeValue<BeanContainer> bc) { ... } // bc from runtime recorder\n// after\n@Record(ExecutionTime.RUNTIME_INIT)\nvoid init(MyRecorder r, RuntimeValue<BeanContainer> bc) { ... }","handlingStrategy":"type-guard","validationCode":"// before passing a proxy into a static-init recorder\nif (proxy instanceof io.quarkus.runtime.annotations.ReturnedProxy rp && !rp.__static$$init()) {\n    throw new IllegalStateException(\"Runtime-init proxy cannot be consumed by a STATIC_INIT recorder\");\n}","typeGuard":"static boolean isStaticInitSafe(Object proxy) {\n    return !(proxy instanceof io.quarkus.runtime.annotations.ReturnedProxy p) || p.__static$$init();\n}","tryCatchPattern":null,"preventionTips":["Match recorder phases: only pass STATIC_INIT-produced proxies to STATIC_INIT recorders","Consume RUNTIME_INIT values only from RUNTIME_INIT @Record methods","Double-check @Record(ExecutionTime.X) on both producer and consumer when wiring recorders"],"tags":["quarkus","recorder","static-init","runtime-init","proxy"],"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"}