{"record":{"id":"0a90ecea99d40b54","repo":"quarkusio/quarkus","slug":"we-found-a-configroot-without-a-corresponding-co","errorCode":null,"errorMessage":"We found a @ConfigRoot without a corresponding @ConfigMapping annotation in: ${configRoot}. Make sure your configuration interfaces are annotated with @ConfigMapping.","messagePattern":"We found a @ConfigRoot without a corresponding @ConfigMapping annotation in: (.+?)\\. Make sure your configuration interfaces are annotated with @ConfigMapping\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/ConfigAnnotationScanner.java","lineNumber":467,"sourceCode":"                if (discoveryRootElement != null) {\n                    throw new IllegalStateException(\"Multiple listeners returned discovery root elements for: \" +\n                            discoveryRootElement.getQualifiedName());\n                }\n\n                discoveryRootElement = discoveryRootElementCandidate.get();\n            }\n        }\n\n        if (discoveryRootElement == null) {\n            throw new IllegalStateException(\"No listeners returned a discovery root element\");\n        }\n\n        return discoveryRootElement;\n    }\n\n    private void checkConfigRootAnnotationConsistency(TypeElement configRoot) {\n        if (!utils.element().isAnnotationPresent(configRoot, Types.ANNOTATION_CONFIG_MAPPING)) {\n            throw new IllegalStateException(\n                    \"We found a @ConfigRoot without a corresponding @ConfigMapping annotation in: \" + configRoot + \".\"\n                            + \" Make sure your configuration interfaces are annotated with @ConfigMapping.\");\n        }\n    }\n\n    private void debug(String debug, Element element) {\n        if (!config.isDebug()) {\n            return;\n        }\n\n        utils.processingEnv().getMessager().printMessage(Kind.NOTE, \"[\" + element.getSimpleName() + \"] \" + debug);\n    }\n}\n","sourceCodeStart":449,"sourceCodeEnd":481,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/processor/src/main/java/io/quarkus/annotation/processor/documentation/config/scanner/ConfigAnnotationScanner.java#L449-L481","documentation":"checkConfigRootAnnotationConsistency enforces that every class annotated with @ConfigRoot is also annotated with @ConfigMapping. Quarkus removed the legacy @ConfigRoot-only configuration class style; a root without @ConfigMapping cannot be processed and documentation scanning aborts with this message naming the offending class.","triggerScenarios":"Compiling a class annotated with @ConfigRoot (any phase/prefix) whose declaration lacks @ConfigMapping — typically after upgrading from an older Quarkus where @ConfigRoot(prefix=..., phase=...) alone was valid.","commonSituations":"Migrating extensions or applications from pre-@ConfigMapping-era Quarkus; copied example code from outdated blogs/docs; custom configuration interfaces written against an old Quarkus version.","solutions":["Add @ConfigMapping (with the prefix) to the named class; keep @ConfigRoot only for phase declaration.","Move the prefix from @ConfigRoot's (removed) prefix attribute into @ConfigMapping(prefix = \"...\").","Regenerate the config class with the Quarkus config mapping code style if migrating.","Update outdated example/tutorial code to the current Quarkus configuration style."],"exampleFix":"// before (legacy)\n@ConfigRoot(prefix = \"myapp\", phase = ConfigPhase.RUN_TIME)\npublic interface MyAppConfig { String name(); }\n\n// after\n@ConfigMapping(prefix = \"myapp\")\n@ConfigRoot(phase = ConfigPhase.RUN_TIME)\npublic interface MyAppConfig { String name(); }","handlingStrategy":"validation","validationCode":"// fail fast in an ArchUnit/unit test during migration\nfor (Class<?> c : allConfigClasses) {\n    if (c.isAnnotationPresent(ConfigRoot.class)\n            && !c.isAnnotationPresent(ConfigMapping.class))\n        throw new IllegalStateException(c + \" needs @ConfigMapping\");\n}","typeGuard":"static boolean hasRequiredAnnotations(Class<?> c) {\n    return !c.isAnnotationPresent(ConfigRoot.class)\n        || c.isAnnotationPresent(ConfigMapping.class);\n}","tryCatchPattern":null,"preventionTips":["When migrating from legacy @ConfigRoot classes, add @ConfigMapping and move the prefix there.","Add a compile-time/architecture test asserting the @ConfigRoot+@ConfigMapping pairing.","Update old tutorial/blog-derived config classes to the current style.","Read Quarkus migration guides on version upgrades before rebuilding."],"tags":["quarkus","config-root","config-mapping","migration","annotation"],"backgroundTag":"missing-required-annotation","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"}