{"record":{"id":"a232c8af83ef4af9","repo":"brettwooldridge/HikariCP","slug":"failed-to-load-class-classname","errorCode":null,"errorMessage":"Failed to load class ${className}","messagePattern":"Failed to load class (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"src/main/java/com/zaxxer/hikari/util/UtilityElf.java","lineNumber":155,"sourceCode":"         for (int i = 0; i < totalArgs; i++) {\n            argClasses[i] = args[i].getClass();\n         }\n\n         Constructor<?> constructor = Arrays.stream(loaded.getConstructors())\n            .filter(c -> {\n               if (c.getParameterCount() != totalArgs) return false;\n\n               Class<?>[] params = c.getParameterTypes();\n               return IntStream.range(0, totalArgs)\n                  .allMatch(i -> params[i].isAssignableFrom(argClasses[i]));\n            })\n            .findFirst()\n            .orElseThrow(() -> new RuntimeException(\"No suitable constructor found for class \" + className + \" with arguments \" + Arrays.toString(args)));\n\n         return clazz.cast(constructor.newInstance(args));\n      }\n      catch (Exception e) {\n         throw new RuntimeException(\"Failed to load class \" + className, e);\n      }\n   }\n\n   /**\n    * Create a ThreadPoolExecutor.\n    *\n    * @param queueSize the queue size\n    * @param threadName the thread name\n    * @param threadFactory an optional ThreadFactory\n    * @param policy the RejectedExecutionHandler policy\n    * @return a ThreadPoolExecutor\n    */\n   public static ThreadPoolExecutor createThreadPoolExecutor(final int queueSize, final String threadName, ThreadFactory threadFactory, final RejectedExecutionHandler policy)\n   {\n      return createThreadPoolExecutor(new LinkedBlockingQueue<>(queueSize), threadName, threadFactory, policy);\n   }\n\n   /**","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/brettwooldridge/HikariCP/blob/a4d93f4f85517f90e632b795486d7102e933d7ff/src/main/java/com/zaxxer/hikari/util/UtilityElf.java#L137-L173","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","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.","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.","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.","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.","Prefer jdbcUrl over driverClassName for JDBC 4+ drivers — they self-register via META-INF/services and you avoid this reflective path entirely."],"exampleFix":"// before (application.properties)\n dataSourceClassName=org.postgresql.ds.PGSimpleDataSource\n driverClassName=org.postgresql.Driver   # -> Driver cast/pool mismatch, or class missing\n\n# after\n spring.datasource.url=jdbc:postgresql://localhost:5432/mydb\n spring.datasource.username=...\n spring.datasource.password=...\n# JDBC 4+ drivers auto-register; no driverClassName/dataSourceClassName reflection needed","handlingStrategy":"validation","validationCode":"// Before building the HikariDataSource, verify the class resolves and casts\nstatic <T> void requireInstantiable(String className, Class<T> requiredType, ClassLoader cl) {\n    Class<?> c = Class.forName(className, false, cl == null ? UtilityElf.class.getClassLoader() : cl);\n    if (!requiredType.isAssignableFrom(c))\n        throw new IllegalArgumentException(className + \" does not implement \" + requiredType.getName());\n    if (Arrays.stream(c.getConstructors()).noneMatch(ctor -> ctor.getParameterCount() == 0))\n        throw new IllegalArgumentException(className + \" has no public no-arg constructor\");\n}\n\n// usage at startup\nrequireInstantiable(config.getDataSourceClassName(), javax.sql.DataSource.class, null);\nrequireInstantiable(config.getCredentialsProviderClassName(), HikariCredentialsProvider.class, null);","typeGuard":null,"tryCatchPattern":"// last-resort wrapper: fail fast with the ROOT cause, not the wrapper\ntry {\n    HikariDataSource ds = new HikariDataSource(config);\n} catch (RuntimeException e) {\n    Throwable root = e;\n    while (root.getCause() != null && root != root.getCause()) root = root.getCause();\n    if (root instanceof ClassNotFoundException cnf)\n        throw new IllegalStateException(\"Missing class on classpath: \" + cnf.getMessage(), root);\n    throw e;\n}","preventionTips":["Prefer jdbcUrl over driverClassName/dataSourceClassName for JDBC 4+ drivers — the driver self-registers and you skip reflection entirely.","Fail fast at startup: create the pool eagerly (new HikariDataSource(config)) instead of lazily, so class/constructor problems surface at deploy time with the real cause.","Write a startup smoke test that builds the HikariConfig exactly as production config does and opens one connection in CI.","For custom credentialsProviderClassName/exceptionOverrideClassName classes, guarantee a public no-arg constructor and the required interface, and unit-test instantiation yourself.","In shaded/fat jars or classloader-isolated runtimes (DevTools, servlet containers), verify the driver jar is loaded by the same classloader as HikariCP."],"tags":["hikaricp","reflection","classloading","configuration","jdbc"],"backgroundTag":null,"analyzedSha":"a4d93f4f85517f90e632b795486d7102e933d7ff","analyzedAt":"2026-08-14T12:11:37.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}