{"record":{"id":"059c7561f8b4d8eb","repo":"quarkusio/quarkus","slug":"the-rolesallowedconfigexpstorage-bean-is-created","errorCode":null,"errorMessage":"The 'RolesAllowedConfigExpStorage' bean is created before runtime configuration is ready","messagePattern":"The 'RolesAllowedConfigExpStorage' bean is created before runtime configuration is ready","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/ResteasyReactiveServerJacksonRecorder.java","lineNumber":58,"sourceCode":"        return new BiConsumer<>() {\n            @Override\n            public void accept(String configKey, Supplier<String[]> configValueSupplier) {\n                configExpToAllowedRoles.getValue().put(configKey, configValueSupplier);\n            }\n        };\n    }\n\n    @StaticInit\n    public Supplier<RolesAllowedConfigExpStorage> createRolesAllowedConfigExpStorage(\n            RuntimeValue<Map<String, Supplier<String[]>>> configExpToAllowedRoles) {\n        return new Supplier<>() {\n            @Override\n            public RolesAllowedConfigExpStorage get() {\n                Map<String, Supplier<String[]>> map = configExpToAllowedRoles.getValue();\n                if (map.isEmpty()) {\n                    // there is no reason why this should happen, because we initialize the bean ourselves\n                    // when runtime configuration is ready\n                    throw new IllegalStateException(\n                            \"The 'RolesAllowedConfigExpStorage' bean is created before runtime configuration is ready\");\n                }\n                return new RolesAllowedConfigExpStorage(configExpToAllowedRoles.getValue());\n            }\n        };\n    }\n\n    @RuntimeInit\n    public void initAndValidateRolesAllowedConfigExp() {\n        Arc.container().instance(RolesAllowedConfigExpStorage.class).get().resolveRolesAllowedConfigExp();\n    }\n\n    public void recordJsonView(String targetId, String className) {\n        jsonViewMap.put(targetId, loadClass(className));\n    }\n\n    public void recordCustomSerialization(String target, String className) {\n        customSerializationMap.put(target, loadClass(className));","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-jackson/runtime/src/main/java/io/quarkus/resteasy/reactive/jackson/runtime/ResteasyReactiveServerJacksonRecorder.java#L40-L76","documentation":"RolesAllowedConfigExpStorage caches resolved security-role configuration expressions for the RESTEasy Reactive Jackson server. Quarkus initializes this singleton bean itself only once runtime configuration is ready; the Supplier's get() throws IllegalStateException if the bean is requested before that initialization ran, indicating a lifecycle/wiring bug (bean created too early) rather than user misconfiguration.","triggerScenarios":"A RolesAllowedConfigExpStorage bean instance is obtained from the generated Supplier before the RuntimeConfigSetup run-time init step populated the config-expression map (e.g. due to a CDI bean ordering issue, custom producer, or extension regression).","commonSituations":"Using quarkus.http.auth... or @RolesAllowed with property expressions (e.g. ${admin.roles}) in combination with custom security extensions; upgrading Quarkus where bean init ordering changed; user code injecting this internal storage bean directly.","solutions":["Ensure you do not inject/observe the internal RolesAllowedConfigExpStorage bean directly; treat it as internal API","Check for custom extensions or producers that touch RolesAllowedConfigExpStorage earlier in startup and delay them (observe RuntimeConfigReady event or use @AllowsConfigInjection patterns)","Verify that any @RolesAllowed / config-expression security setup is declared normally (application.properties values present) so runtime config resolves on time","If it occurs in a stock app, isolate a reproducer and report a Quarkus bug — this indicates an initialization-order regression"],"exampleFix":"// before\n@ApplicationScoped\nclass MyBean {\n    RolesAllowedConfigExpStorage storage; // early injection of internal bean\n}\n\n// after\n@ApplicationScoped\nclass MyBean {\n    void onStart(@Observes RuntimeConfigReady ev) { /* access config-dependent state here */ }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    RolesAllowedConfigExpStorage s = storageSupplier.get();\n} catch (IllegalStateException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"runtime configuration is ready\")) {\n        // defer access until runtime config is initialized (e.g. observe RuntimeConfigReady)\n    }\n}","preventionTips":["Do not inject or reference internal RolesAllowedConfigExpStorage beans directly","Access config-dependent security state only after runtime configuration is ready","Avoid custom producers that instantiate this bean earlier in startup","Report occurrences in stock apps as Quarkus initialization-order bugs"],"tags":["quarkus","lifecycle","security","runtime-config"],"backgroundTag":"bean-initialized-before-config-ready","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}