{"record":{"id":"780458a7314b7c5a","repo":"quarkusio/quarkus","slug":"the-configuration-clazz-is-missing-the-configr","errorCode":null,"errorMessage":"The configuration ${clazz} is missing the @ConfigRoot annotation","messagePattern":"The configuration (.+?) is missing the @ConfigRoot annotation","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java","lineNumber":65,"sourceCode":"/**\n * A configuration reader.\n */\npublic final class BuildTimeConfigurationReader {\n    private static final String CONFIG_ROOTS_LIST = \"META-INF/quarkus-config-roots.list\";\n\n    private static List<Class<?>> collectConfigRoots(ClassLoader classLoader) throws IOException, ClassNotFoundException {\n        Assert.checkNotNullParam(\"classLoader\", classLoader);\n        // populate with all known types\n        List<Class<?>> roots = new ArrayList<>();\n        for (Class<?> clazz : ServiceUtil.classesNamedIn(classLoader, CONFIG_ROOTS_LIST)) {\n            if (!clazz.isInterface()) {\n                throw new IllegalArgumentException(\n                        \"The configuration \" + clazz + \" must be an interface annotated with @ConfigRoot and @ConfigMapping\");\n            }\n\n            ConfigRoot configRoot = clazz.getAnnotation(ConfigRoot.class);\n            if (configRoot == null) {\n                throw new IllegalArgumentException(\"The configuration \" + clazz + \" is missing the @ConfigRoot annotation\");\n            }\n\n            ConfigMapping configMapping = clazz.getAnnotation(ConfigMapping.class);\n            if (configMapping == null) {\n                throw new IllegalArgumentException(\"The configuration \" + clazz + \" is missing the @ConfigMapping annotation\");\n            }\n\n            roots.add(clazz);\n        }\n        return roots;\n    }\n\n    private final ClassLoader classLoader;\n\n    private final List<ConfigClass> buildTimeMappings;\n    private final List<ConfigClass> buildTimeRunTimeMappings;\n    private final List<ConfigClass> runTimeMappings;\n    private final List<ConfigClass> buildTimeVisibleMappings;","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java#L47-L83","documentation":"During build-time configuration scanning, collectConfigRoots in BuildTimeConfigurationReader inspects every configuration class and requires it to carry the @ConfigRoot annotation. When a class passed in the config roots set lacks @ConfigRoot (while possibly having @ConfigMapping), the reader rejects it with this IllegalArgumentException. @ConfigRoot supplies the extension name and phase metadata Quarkus needs to map config interfaces to their quarkus.* prefix.","triggerScenarios":"An interface implementing application configuration is registered as a config root (via the ConfigClassBuildItem / CollectBuildTimeConfig build step) but is only annotated with @ConfigMapping, missing @ConfigRoot(phase = ..., prefix = ...).","commonSituations":"Extension authors writing a custom @ConfigMapping interface and forgetting the required @ConfigRoot annotation; copying a Spring Boot @ConfigurationProperties-style class into Quarkus; refactoring that removes annotations thought to be optional.","solutions":["Add @ConfigRoot(phase = ConfigPhase.BUILD_TIME (or RUN_TIME as appropriate), prefix = \"<extension>\") to the configuration interface.","Ensure the class is actually an interface; @ConfigRoot on classes is not the intended usage.","Rebuild the deployment module so the annotation is processed by the CollectBuildTimeConfig build step."],"exampleFix":"// before\n@ConfigMapping(prefix = \"myext\")\npublic interface MyExtConfig { }\n\n// after\n@ConfigRoot(phase = ConfigPhase.BUILD_TIME, prefix = \"myext\")\n@ConfigMapping(prefix = \"myext\")\npublic interface MyExtConfig { }","handlingStrategy":"validation","validationCode":"MyConfig.class.isInterface()\n    && MyConfig.class.isAnnotationPresent(ConfigRoot.class)\n    && MyConfig.class.isAnnotationPresent(ConfigMapping.class);","typeGuard":"static boolean isConfigRoot(Class<?> c) {\n    return c.isInterface() && c.isAnnotationPresent(ConfigRoot.class);\n}","tryCatchPattern":null,"preventionTips":["Always pair @ConfigMapping with @ConfigRoot on extension config interfaces.","Use the Quarkus extension code generation (quarkus-maven-plugin create-extension) which scaffolds correct annotations.","Test extension builds early so CollectBuildTimeConfig fails fast."],"tags":["quarkus","configuration","annotation","build-time"],"backgroundTag":"missing-annotation","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"}