quarkusio/quarkus · error · ConfigurationException
Thread pool class not found: ${threadPoolClass}
Error message
Thread pool class not found: ${threadPoolClass} What it means
Quarkus Quartz deployment validates the custom thread pool class configured via quarkus.quartz.thread-pool.class by loading it with Class.forName at build time. When the class cannot be found on the application classpath, a ConfigurationException with this message is thrown, failing the build. This guard exists so Quartz can instantiate the pool and register it for reflection (native image support).
Source
Thrown at extensions/quartz/deployment/src/main/java/io/quarkus/quartz/deployment/QuartzProcessor.java:249
reflectiveClasses.add(ReflectiveClassBuildItem.builder(
String.class,
JobDataMap.class,
DirtyFlagMap.class,
StringKeyDirtyFlagMap.class,
HashMap.class)
.reason(getClass().getName())
.serialization(true).build());
}
Class<?> threadPoolClass;
try {
threadPoolClass = Class.forName(config.threadPoolClass(), false, Thread.currentThread().getContextClassLoader());
if (!ThreadPool.class.isAssignableFrom(threadPoolClass)) {
throw new ConfigurationException(
"Thread pool class does not implement ThreadPool interface spi: " + config.threadPoolClass());
}
} catch (ClassNotFoundException e) {
throw new ConfigurationException("Thread pool class not found: " + config.threadPoolClass());
}
reflectiveClasses.add(ReflectiveClassBuildItem.builder(threadPoolClass, SimpleInstanceIdGenerator.class)
.reason(getClass().getName())
.methods().build());
reflectiveClasses
.add(ReflectiveClassBuildItem.builder(CascadingClassLoadHelper.class, InitThreadContextClassLoadHelper.class)
.reason(getClass().getName())
.build());
reflectiveClasses.add(ReflectiveClassBuildItem.builder(config.storeType().clazz)
.reason(getClass().getName())
.methods().fields().build());
if (config.storeType().isDbStore()) {
reflectiveClasses.add(ReflectiveClassBuildItem.builder(
JobStoreSupport.class,
AbstractTrigger.class,
SimpleTriggerImpl.class,View on GitHub (pinned to e1c734241f)
Solutions
- Verify the fully-qualified class name in quarkus.quartz.thread-pool.class (check spelling and package).
- Add the artifact containing the ThreadPool implementation as a dependency of the application.
- Ensure the class implements org.quarkus... org.quartz.spi.ThreadPool (the next validation would reject it otherwise).
- If no custom pool is needed, remove the property to fall back to the default thread pool.
Example fix
// before (application.properties) quarkus.quartz.thread-pool.class=com.myapp.CustomPool // after (correct FQN + dependency present) quarkus.quartz.thread-pool.class=com.myapp.quartz.CustomThreadPool
Defensive patterns
Strategy: validation
Validate before calling
// build-time check: ensure the class is loadable and implements ThreadPool
String fqn = "com.myapp.quartz.CustomThreadPool"; // value of quarkus.quartz.thread-pool.class
try {
Class<?> c = Class.forName(fqn, false, Thread.currentThread().getContextClassLoader());
if (!org.quartz.spi.ThreadPool.class.isAssignableFrom(c)) {
throw new IllegalStateException(fqn + " must implement org.quartz.spi.ThreadPool");
}
} catch (ClassNotFoundException e) {
throw new IllegalStateException("thread-pool class not on classpath: " + fqn, e);
} Prevention
- Keep the custom ThreadPool in a module that is a compile+runtime dependency of the app.
- Reference the class via Class literal where possible to catch typos at compile time.
- Run a build before deploying; this error surfaces at build time, not runtime.
When it happens
Trigger: Set quarkus.quartz.thread-pool.class to a class name that is not on the application's classpath at build time (typo, missing dependency, wrong package, class only available at runtime).
Common situations: Typo in the fully-qualified class name; custom ThreadPool implementation lives in a module not declared as a dependency; class was renamed/moved during a Quartz or app upgrade; using a library thread pool class excluded from the Quarkus app.
Related errors
- Clustered jobs configured with unsupported job store option
- Quartz datasource resolution can be either deferred to runti
- The configuration ${clazz} is missing the @ConfigRoot annota
- Unable to load the datasource driver <driverName> for the <f
- Invalid configuration value set for 'quarkus.arc.remove-unus
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/d0c9357c693fdd08.
Report an issue: GitHub.