{"record":{"id":"68a282ad1061fc21","repo":"quarkusio/quarkus","slug":"multiple-healthcheckresponseprovider-implementatio","errorCode":null,"errorMessage":"Multiple HealthCheckResponseProvider implementations found: %s","messagePattern":"Multiple HealthCheckResponseProvider implementations found: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java","lineNumber":187,"sourceCode":"        beanDefiningAnnotation.produce(new BeanDefiningAnnotationBuildItem(HEALTH_GROUPS, BuiltinScope.SINGLETON.getName()));\n        beanDefiningAnnotation.produce(new BeanDefiningAnnotationBuildItem(WELLNESS, BuiltinScope.SINGLETON.getName()));\n\n        // Add additional beans\n        additionalBean.produce(new AdditionalBeanBuildItem(QuarkusAsyncHealthCheckFactory.class));\n        excludedTypes.produce(new ExcludedTypeBuildItem(AsyncHealthCheckFactory.class.getName()));\n        additionalBean.produce(new AdditionalBeanBuildItem(SmallRyeHealthReporter.class));\n\n        // Make ArC discover @HealthGroup as a qualifier\n        additionalBean.produce(new AdditionalBeanBuildItem(HealthGroup.class));\n\n        // Discover and register the HealthCheckResponseProvider\n        Set<String> providers = ServiceUtil.classNamesNamedIn(getClass().getClassLoader(),\n                \"META-INF/services/\" + HealthCheckResponseProvider.class.getName());\n\n        if (providers.isEmpty()) {\n            throw new IllegalStateException(\"No HealthCheckResponseProvider implementation found.\");\n        } else if (providers.size() > 1) {\n            throw new IllegalStateException(\n                    String.format(\"Multiple HealthCheckResponseProvider implementations found: %s\", providers));\n        }\n\n        final String provider = providers.iterator().next();\n        final Class<? extends HealthCheckResponseProvider> responseProvider = (Class<? extends HealthCheckResponseProvider>) Class\n                .forName(provider, true, Thread.currentThread().getContextClassLoader());\n        recorder.registerHealthCheckResponseProvider(responseProvider);\n    }\n\n    @BuildStep\n    public void defineHealthRoutes(BuildProducer<RouteBuildItem> routes,\n            BeanArchiveIndexBuildItem beanArchiveIndex,\n            NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem,\n            SmallRyeHealthBuildTimeConfig healthConfig) {\n        IndexView index = beanArchiveIndex.getIndex();\n\n        // log a warning if users try to use MP Health annotations with JAX-RS @Path\n        warnIfJaxRsPathUsed(index, LIVENESS);","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java#L169-L205","documentation":"The health extension build step requires exactly one HealthCheckResponseProvider implementation discovered through ServiceLoader. When more than one implementation is registered in META-INF/services/org.eclipse.microprofile.health.HealthCheckResponseProvider across the classpath, the build fails with this IllegalStateException listing all found providers, since the choice would be ambiguous.","triggerScenarios":"Two or more jars each ship META-INF/services/org.eclipse.microprofile.health.HealthCheckResponseProvider — e.g. both the smallrye-health CDI provider and another implementation (or two copies/versions of smallrye-health) on the build classpath.","commonSituations":"Mixed SmallRye Health versions in the dependency tree; an app depending on both quarkus-smallrye-health and raw smallrye-health artifacts from different releases; shaded jars that duplicate the services file; adding a second MP Health implementation for testing.","solutions":["Run mvn dependency:tree, find duplicates of smallrye-health, and exclude the unwanted copy so exactly one provider remains","Align SmallRye Health versions via the Quarkus BOM and remove manually declared smallrye-health artifacts","Remove any additional MP Health implementation dependency that ships its own provider"],"exampleFix":"// before — two sources of the provider\n<dependency>io.smallrye:smallrye-health:3.1.0</dependency>\n<dependency>\n  <groupId>io.quarkus</groupId>\n  <artifactId>quarkus-smallrye-health</artifactId>\n</dependency>\n\n// after — only the extension, versions managed by the BOM\n<dependency>\n  <groupId>io.quarkus</groupId>\n  <artifactId>quarkus-smallrye-health</artifactId>\n</dependency>","handlingStrategy":"validation","validationCode":"Set<String> providers = ServiceUtil.classNamesNamedIn(getClass().getClassLoader(),\n        \"META-INF/services/org.eclipse.microprofile.health.HealthCheckResponseProvider\");\nif (providers.size() > 1) {\n    throw new IllegalStateException(\"Exactly one HealthCheckResponseProvider allowed, found: \" + providers);\n}","typeGuard":null,"tryCatchPattern":"try {\n    quarkusBuild();\n} catch (IllegalStateException e) {\n    if (e.getMessage().startsWith(\"Multiple HealthCheckResponseProvider\")) {\n        throw new IllegalStateException(\"Deduplicate smallrye-health on the classpath: \" + e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Import io.quarkus.platform:quarkus-bom and never pin smallrye-health manually","Check dependency:tree for duplicated artifacts in CI","Enforce maven-enforcer dependencyConvergence rules","Avoid shaded jars that bundle services descriptors"],"tags":["health","build-time","serviceloader","dependency-conflict","quarkus"],"backgroundTag":"duplicate-service-provider","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"}