eclipse-vertx/vert.x · error · IllegalStateException

Cannot find META-INF/services/${clazz} on classpath

Error message

Cannot find META-INF/services/${clazz} on classpath

What it means

Deprecated ServiceHelper.loadFactory(Class) uses the old ServiceLoader file lookup; if no implementation of clazz is registered under META-INF/services/<class name>, IllegalStateException('Cannot find META-INF/services/<clazz> on classpath') is thrown. It signals a required SPI implementation is missing from the runtime classpath.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/impl/ServiceHelper.java:27

 * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 */

package io.vertx.core.impl;

import java.util.*;

/**
 * A helper class for loading factories from the classpath.
 *
 * @author <a href="http://tfox.org">Tim Fox</a>
 */
public class ServiceHelper {

  @Deprecated
  public static <T> T loadFactory(Class<T> clazz) {
    T factory = loadFactoryOrNull(clazz);
    if (factory == null) {
      throw new IllegalStateException("Cannot find META-INF/services/" + clazz.getName() + " on classpath");
    }
    return factory;
  }

  @Deprecated
  public static <T> T loadFactoryOrNull(Class<T> clazz) {
    Collection<T> collection = loadFactories(clazz);
    if (!collection.isEmpty()) {
      return collection.iterator().next();
    } else {
      return null;
    }
  }

  @Deprecated
  public static <T> List<T> loadFactories(Class<T> clazz) {
    return loadFactories(clazz, null);
  }

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Add the dependency that provides the SPI implementation (e.g. io.vertx:vertx-hazelcast for clustering)
  2. Ensure your build/shading tool merges META-INF/services files (ServicesResourceTransformer for shade, mergeServiceFiles for Gradle)
  3. If on JPMS, add a provides ... with ... clause in module-info
  4. Migrate to the non-deprecated overload taking a ServiceLoader or ServiceHelper.loadFactoryOrNull with a fallback

Example fix

// before
ClusterManager cm = ServiceHelper.loadFactory(ClusterManagerFactory.class).newManager();
// after
ClusterManager cm = Optional.ofNullable(ServiceHelper.loadFactoryOrNull(ClusterManagerFactory.class))
    .map(ClusterManagerFactory::newManager)
    .orElseGet(HazelcastClusterManager::new);
Defensive patterns

Strategy: fallback

Validate before calling

ClusterManagerFactory f = ServiceHelper.loadFactoryOrNull(ClusterManagerFactory.class);
if (f == null) throw new IllegalStateException("Add the clustering provider jar to the classpath");

Try / catch

try { factory = ServiceHelper.loadFactory(Spi.class); } catch (IllegalStateException e) { log.error("Missing SPI provider: add the implementation jar (check META-INF/services)"); throw e; }

Prevention

When it happens

Trigger: Calling loadFactory(SomeSpi.class) (or Vert.x internals resolving e.g. ClusterManagerFactory, LogDelegateFactory, DNS resolver providers) when no provider file exists on the classpath.

Common situations: Building an uber-jar that strips META-INF/services entries; forgetting to add the provider implementation dependency (e.g. vertx-clustering-implementations) at runtime; packaging as JPMS module without 'provides' clauses.

Understand the failure class

Background: "X is not installed. Please install it with pip install Y": missing optional dependency errors — ImportError/ValueError raised when a library's optional extra was never installed — this error's family across 22 libraries.

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/4253a72441baebcc. Report an issue: GitHub.