quarkusio/quarkus · error · IllegalStateException
Multiple HealthCheckResponseProvider implementations found:
Error message
Multiple HealthCheckResponseProvider implementations found: %s
What it means
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.
Source
Thrown at extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java:187
beanDefiningAnnotation.produce(new BeanDefiningAnnotationBuildItem(HEALTH_GROUPS, BuiltinScope.SINGLETON.getName()));
beanDefiningAnnotation.produce(new BeanDefiningAnnotationBuildItem(WELLNESS, BuiltinScope.SINGLETON.getName()));
// Add additional beans
additionalBean.produce(new AdditionalBeanBuildItem(QuarkusAsyncHealthCheckFactory.class));
excludedTypes.produce(new ExcludedTypeBuildItem(AsyncHealthCheckFactory.class.getName()));
additionalBean.produce(new AdditionalBeanBuildItem(SmallRyeHealthReporter.class));
// Make ArC discover @HealthGroup as a qualifier
additionalBean.produce(new AdditionalBeanBuildItem(HealthGroup.class));
// Discover and register the HealthCheckResponseProvider
Set<String> providers = ServiceUtil.classNamesNamedIn(getClass().getClassLoader(),
"META-INF/services/" + HealthCheckResponseProvider.class.getName());
if (providers.isEmpty()) {
throw new IllegalStateException("No HealthCheckResponseProvider implementation found.");
} else if (providers.size() > 1) {
throw new IllegalStateException(
String.format("Multiple HealthCheckResponseProvider implementations found: %s", providers));
}
final String provider = providers.iterator().next();
final Class<? extends HealthCheckResponseProvider> responseProvider = (Class<? extends HealthCheckResponseProvider>) Class
.forName(provider, true, Thread.currentThread().getContextClassLoader());
recorder.registerHealthCheckResponseProvider(responseProvider);
}
@BuildStep
public void defineHealthRoutes(BuildProducer<RouteBuildItem> routes,
BeanArchiveIndexBuildItem beanArchiveIndex,
NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem,
SmallRyeHealthBuildTimeConfig healthConfig) {
IndexView index = beanArchiveIndex.getIndex();
// log a warning if users try to use MP Health annotations with JAX-RS @Path
warnIfJaxRsPathUsed(index, LIVENESS);View on GitHub (pinned to e1c734241f)
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
Example fix
// before — two sources of the provider <dependency>io.smallrye:smallrye-health:3.1.0</dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-health</artifactId> </dependency> // after — only the extension, versions managed by the BOM <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-health</artifactId> </dependency>
Defensive patterns
Strategy: validation
Validate before calling
Set<String> providers = ServiceUtil.classNamesNamedIn(getClass().getClassLoader(),
"META-INF/services/org.eclipse.microprofile.health.HealthCheckResponseProvider");
if (providers.size() > 1) {
throw new IllegalStateException("Exactly one HealthCheckResponseProvider allowed, found: " + providers);
} Try / catch
try {
quarkusBuild();
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Multiple HealthCheckResponseProvider")) {
throw new IllegalStateException("Deduplicate smallrye-health on the classpath: " + e.getMessage(), e);
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No HealthCheckResponseProvider implementation found.
- Failed to open path tree with root %s
- Dev services for ${request.getName()} requires a startable s
- Name cannot start with '/':${name}
- The class (${name}) cannot be created during deployment.
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/68a282ad1061fc21.
Report an issue: GitHub.