quarkusio/quarkus · critical · IllegalArgumentException
Starting with Quarkus 3.25, legacy config classes (deprecate
Error message
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.
What it means
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.
Source
Thrown at core/processor/src/main/java/io/quarkus/annotation/processor/ExtensionAnnotationProcessor.java:47
@SupportedOptions({ Options.LEGACY_CONFIG_ROOT, Options.GENERATE_DOC, Options.SPLIT_ON_CONFIG_ROOT_DESCRIPTION })
public class ExtensionAnnotationProcessor extends AbstractProcessor {
private static final String DEBUG = "debug-extension-annotation-processor";
private Utils utils;
private List<ExtensionProcessor> extensionProcessors;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
utils = new Utils(processingEnv);
boolean useConfigMapping = !Boolean
.parseBoolean(utils.processingEnv().getOptions().getOrDefault(Options.LEGACY_CONFIG_ROOT, "false"));
if (!useConfigMapping) {
throw new IllegalArgumentException(
"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.");
}
boolean debug = Boolean.getBoolean(DEBUG);
ExtensionModule extensionModule = utils.extension().getExtensionModule();
Config config = new Config(extensionModule, debug);
List<ExtensionProcessor> extensionProcessors = new ArrayList<>();
extensionProcessors.add(new ExtensionBuildProcessor());
boolean generateDoc = !"false".equals(processingEnv.getOptions().get(Options.GENERATE_DOC));
// for now, we generate the old config doc by default but we will change this behavior soon
if (generateDoc) {
if (extensionModule.detected()) {View on GitHub (pinned to e1c734241f)
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
Example fix
// before
@ConfigRoot(name = "myext", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
public class MyExtConfig {
@ConfigItem public String name;
}
// after
@ConfigMapping(prefix = "myext")
public interface MyExtConfig {
String name();
} Defensive patterns
Strategy: validation
Validate before calling
// Ensure no legacy config classes remain before upgrading: grep -rl "@ConfigRoot" extensions/*/runtime/src/main/java || echo "OK: no legacy config roots"
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Either @ConfigRoot or @ConfigMapping is missing on ${configR
- The configuration ${clazz} must be an interface annotated wi
- The supplied 'main-class' value of '${mainClassName}' does n
- Unable to get element as unwrappedType is not a DeclaredType
- Two config roots with different extensions or prefixes canno
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/f778a86063409f66.
Report an issue: GitHub.