{"record":{"id":"f778a86063409f66","repo":"quarkusio/quarkus","slug":"starting-with-quarkus-3-25-legacy-config-classes","errorCode":null,"errorMessage":"Starting with Quarkus 3.25, legacy config classes (deprecated since Quarkus 3.19) are not supported anymore. Please migrate the configuration of your extension to interfaces annotated with @ConfigMapping. See https://quarkus.io/guides/config-mappings#config-mappings for more information.","messagePattern":"Starting with Quarkus 3\\.25, legacy config classes \\(deprecated since Quarkus 3\\.19\\) are not supported anymore\\. Please migrate the configuration of your extension to interfaces annotated with @ConfigMapping\\. See https://quarkus\\.io/guides/config-mappings#config-mappings for more information\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"critical","filePath":"core/processor/src/main/java/io/quarkus/annotation/processor/ExtensionAnnotationProcessor.java","lineNumber":47,"sourceCode":"@SupportedOptions({ Options.LEGACY_CONFIG_ROOT, Options.GENERATE_DOC, Options.SPLIT_ON_CONFIG_ROOT_DESCRIPTION })\npublic class ExtensionAnnotationProcessor extends AbstractProcessor {\n\n    private static final String DEBUG = \"debug-extension-annotation-processor\";\n\n    private Utils utils;\n    private List<ExtensionProcessor> extensionProcessors;\n\n    @Override\n    public synchronized void init(ProcessingEnvironment processingEnv) {\n        super.init(processingEnv);\n\n        utils = new Utils(processingEnv);\n\n        boolean useConfigMapping = !Boolean\n                .parseBoolean(utils.processingEnv().getOptions().getOrDefault(Options.LEGACY_CONFIG_ROOT, \"false\"));\n\n        if (!useConfigMapping) {\n            throw new IllegalArgumentException(\n                    \"Starting with Quarkus 3.25, legacy config classes (deprecated since Quarkus 3.19) are not supported anymore. \"\n                            + \"Please migrate the configuration of your extension to interfaces annotated with @ConfigMapping. See https://quarkus.io/guides/config-mappings#config-mappings for more information.\");\n        }\n\n        boolean debug = Boolean.getBoolean(DEBUG);\n\n        ExtensionModule extensionModule = utils.extension().getExtensionModule();\n\n        Config config = new Config(extensionModule, debug);\n\n        List<ExtensionProcessor> extensionProcessors = new ArrayList<>();\n        extensionProcessors.add(new ExtensionBuildProcessor());\n\n        boolean generateDoc = !\"false\".equals(processingEnv.getOptions().get(Options.GENERATE_DOC));\n\n        // for now, we generate the old config doc by default but we will change this behavior soon\n        if (generateDoc) {\n            if (extensionModule.detected()) {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/processor/src/main/java/io/quarkus/annotation/processor/ExtensionAnnotationProcessor.java#L29-L65","documentation":"The Quarkus extension annotation processor now hard-fails at build time when an extension still uses legacy @ConfigRoot config classes. Legacy config classes (deprecated since Quarkus 3.19) are unsupported as of Quarkus 3.25; extensions must migrate to @ConfigMapping interfaces.","triggerScenarios":"Building an extension whose config classes extend ConfigRoot with the annotation processor active, without setting Options.LEGACY_CONFIG_ROOT=true; the processor's init() throws immediately.","commonSituations":"Upgrading a custom/third-party Quarkus extension from 3.19–3.24 to 3.25+ while keeping old @ConfigRoot classes; vendoring an unmaintained extension into a new build.","solutions":["Migrate the extension's config classes to interfaces annotated with @ConfigMapping per https://quarkus.io/guides/config-mappings","Temporarily pass -AlegacyConfigRoot=true to keep the old behavior while migrating (short-term only)","Pin to a pre-3.25 Quarkus version until migration is feasible","Use the quarkus-maven-plugin / config migration guidance to auto-convert config classes"],"exampleFix":"// before\n@ConfigRoot(name = \"myext\", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)\npublic class MyExtConfig {\n    @ConfigItem public String name;\n}\n// after\n@ConfigMapping(prefix = \"myext\")\npublic interface MyExtConfig {\n    String name();\n}","handlingStrategy":"validation","validationCode":"// Ensure no legacy config classes remain before upgrading:\ngrep -rl \"@ConfigRoot\" extensions/*/runtime/src/main/java || echo \"OK: no legacy config roots\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Migrate to @ConfigMapping interfaces before upgrading past Quarkus 3.25","Run the annotation processor in CI so legacy usage fails fast","Watch deprecation warnings from Quarkus 3.19+ and act on them","Never rely on -AlegacyConfigRoot=true as a long-term workaround"],"tags":["annotation-processor","config","migration","build-time"],"backgroundTag":"legacy-config-root-removed","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"}