brettwooldridge/HikariCP · critical · RuntimeException

Failed to load class ${className}

Error message

Failed to load class ${className}

What it means

HikariCP's UtilityElf.createInstance(className, clazz, args...) reflectively loads a class and invokes a matching constructor; this RuntimeException is the catch-all wrapper thrown when any step of that reflection pipeline fails (class not found, no matching constructor, constructor threw, or the result cannot be cast to the expected type). The original cause (ClassNotFoundException, NoSuchMethodException, InvocationTargetException, ClassCastException, etc.) is attached as the cause. It is hit indirectly through HikariConfig/PoolBase/HikariPool when configuring dataSourceClassName, driverClassName, credentialsProviderClassName, exceptionOverrideClassName, or when HikariCP auto-registers a metrics tracker (Dropwizard/Codahale/Micrometer).

Source

Thrown at src/main/java/com/zaxxer/hikari/util/UtilityElf.java:155

         for (int i = 0; i < totalArgs; i++) {
            argClasses[i] = args[i].getClass();
         }

         Constructor<?> constructor = Arrays.stream(loaded.getConstructors())
            .filter(c -> {
               if (c.getParameterCount() != totalArgs) return false;

               Class<?>[] params = c.getParameterTypes();
               return IntStream.range(0, totalArgs)
                  .allMatch(i -> params[i].isAssignableFrom(argClasses[i]));
            })
            .findFirst()
            .orElseThrow(() -> new RuntimeException("No suitable constructor found for class " + className + " with arguments " + Arrays.toString(args)));

         return clazz.cast(constructor.newInstance(args));
      }
      catch (Exception e) {
         throw new RuntimeException("Failed to load class " + className, e);
      }
   }

   /**
    * Create a ThreadPoolExecutor.
    *
    * @param queueSize the queue size
    * @param threadName the thread name
    * @param threadFactory an optional ThreadFactory
    * @param policy the RejectedExecutionHandler policy
    * @return a ThreadPoolExecutor
    */
   public static ThreadPoolExecutor createThreadPoolExecutor(final int queueSize, final String threadName, ThreadFactory threadFactory, final RejectedExecutionHandler policy)
   {
      return createThreadPoolExecutor(new LinkedBlockingQueue<>(queueSize), threadName, threadFactory, policy);
   }

   /**

View on GitHub (pinned to a4d93f4f85)

Solutions

  1. Read the attached cause of the RuntimeException (e.getCause()) — it tells you exactly which stage failed: ClassNotFoundException = wrong name/missing jar, NoSuchMethodException/'No suitable constructor' = constructor signature problem, InvocationTargetException = your constructor threw, ClassCastException = wrong interface.
  2. Verify the dependency containing the class is on the runtime classpath (not just compile scope; check it is not test/provided if this happens only in prod) and that the FQCN string has no typo or extra whitespace.
  3. If the class is yours (credentials provider, SQLExceptionOverride, DataSource), give it a public no-arg constructor (or a public constructor matching the args HikariCP passes) and make it implement the required HikariCP interface.
  4. In classloader-isolated environments (Spring Boot DevTools, servlet containers), ensure the driver/HikariCP classes are loaded by the same classloader, or set the TCCL appropriately; with DevTools put the driver in the 'restart' classloader or uninstall DevTools for the offending jar.
  5. If a shaded/relocated build broke internal metric factory names, either exclude the half-present metrics library from the classpath or add the correct full dependency so the built-in tracker can load and link.
  6. Prefer jdbcUrl over driverClassName for JDBC 4+ drivers — they self-register via META-INF/services and you avoid this reflective path entirely.

Example fix

// before (application.properties)
 dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
 driverClassName=org.postgresql.Driver   # -> Driver cast/pool mismatch, or class missing

# after
 spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
 spring.datasource.username=...
 spring.datasource.password=...
# JDBC 4+ drivers auto-register; no driverClassName/dataSourceClassName reflection needed
Defensive patterns

Strategy: validation

Validate before calling

// Before building the HikariDataSource, verify the class resolves and casts
static <T> void requireInstantiable(String className, Class<T> requiredType, ClassLoader cl) {
    Class<?> c = Class.forName(className, false, cl == null ? UtilityElf.class.getClassLoader() : cl);
    if (!requiredType.isAssignableFrom(c))
        throw new IllegalArgumentException(className + " does not implement " + requiredType.getName());
    if (Arrays.stream(c.getConstructors()).noneMatch(ctor -> ctor.getParameterCount() == 0))
        throw new IllegalArgumentException(className + " has no public no-arg constructor");
}

// usage at startup
requireInstantiable(config.getDataSourceClassName(), javax.sql.DataSource.class, null);
requireInstantiable(config.getCredentialsProviderClassName(), HikariCredentialsProvider.class, null);

Try / catch

// last-resort wrapper: fail fast with the ROOT cause, not the wrapper
try {
    HikariDataSource ds = new HikariDataSource(config);
} catch (RuntimeException e) {
    Throwable root = e;
    while (root.getCause() != null && root != root.getCause()) root = root.getCause();
    if (root instanceof ClassNotFoundException cnf)
        throw new IllegalStateException("Missing class on classpath: " + cnf.getMessage(), root);
    throw e;
}

Prevention

When it happens

Trigger: Setting dataSourceClassName or driverClassName to a class not on the classpath; naming a class whose constructor is private or whose signature does not match the args createInstance passes; the target constructor throwing an exception during newInstance; the loaded class not implementing the required interface (DataSource, Driver, HikariCredentialsProvider, SQLExceptionOverride, IMetricsTrackerFactory) causing the clazz.cast() to fail; having dropwizard-metrics or micrometer partially on the classpath so HikariPool tries to instantiate the built-in metrics factory that cannot link; shaded/relocated jars where the FQCN string no longer matches the relocated package.

Common situations: Typos in dataSourceClassName in application.properties/yml; missing JDBC driver dependency (e.g. forgot postgresql or mysql-connector-j in pom.gradle); using driverClassName for a driver that only supports DataSource (e.g. with newer drivers, or OSGi/classloader-isolated containers like Tomcat webapps, WildFly, Spring Boot DevTools restartable classloaders); specifying a custom credentialsProviderClassName/exceptionOverrideClassName whose class lacks a public no-arg constructor; upgrading a metrics library to an incompatible version so the internal Codahale/Dropwizard/Micrometer tracker class fails to initialize; fat-jar/shade plugins relocating packages without reflecting the rename in configured class names.

Related errors


AI-assisted analysis of brettwooldridge/HikariCP@a4d93f4f85 (2026-08-14). Data as JSON: /api/errors/a232c8af83ef4af9. Report an issue: GitHub.