quarkusio/quarkus · error · ConfigurationException

Thread pool class does not implement ThreadPool interface sp

Error message

Thread pool class does not implement ThreadPool interface spi: ${threadPoolClass}

What it means

During the reflectiveClasses build step, QuartzProcessor loads the class configured via quarkus.quartz.thread-pool-class and verifies it implements org.quartz.spi.ThreadPool, since it is passed to Quartz's scheduler. The class loaded fine but does not implement that SPI interface, so the build fails. Quartz requires any thread pool to honor this interface.

Source

Thrown at extensions/quartz/deployment/src/main/java/io/quarkus/quartz/deployment/QuartzProcessor.java:245

            QuartzJDBCDriverDialectBuildItem driverDialect, List<JdbcDataSourceBuildItem> jdbcDataSourceBuildItems) {
        List<ReflectiveClassBuildItem> reflectiveClasses = new ArrayList<>();

        if (config.serializeJobData()) {
            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()) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Point quarkus.quartz.thread-pool-class at a class implementing org.quartz.spi.ThreadPool, e.g. io.quarkus.quartz.runtime.QuarkusSimpleThreadPool (the default) or org.quartz.simpl.SimpleThreadPool.
  2. If you meant a JDK executor, wrap it in a class that implements org.quartz.spi.ThreadPool instead of referencing it directly.
  3. Remove the property entirely to use the Quarkus default thread pool.
  4. If the class was refactored, make it implement ThreadPool again or update the config to the correct class.

Example fix

// before (application.properties)
quarkus.quartz.thread-pool-class=java.util.concurrent.ThreadPoolExecutor

// after
quarkus.quartz.thread-pool-class=org.quartz.simpl.SimpleThreadPool
// or a custom class:
// public class MyThreadPool implements org.quartz.spi.ThreadPool { ... }
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName("com.example.MyThreadPool", false,
    Thread.currentThread().getContextClassLoader());
if (!org.quartz.spi.ThreadPool.class.isAssignableFrom(c)) {
    throw new IllegalStateException(c.getName() + " must implement org.quartz.spi.ThreadPool");
}

Type guard

static boolean isThreadPool(Class<?> c) {
    return org.quartz.spi.ThreadPool.class.isAssignableFrom(c);
}

Prevention

When it happens

Trigger: Setting quarkus.quartz.thread-pool-class=<fqcn> to a class that does not implement org.quartz.spi.ThreadPool - e.g. a java.util.concurrent ExecutorService implementation, a custom pool class, or an unrelated class; or a custom pool whose ThreadPool implementation was removed in a refactor/upgrade.

Common situations: Misreading the property as accepting JDK executor implementations; copying a class name from plain Quartz configs of a different type; dependency upgrades that changed what the class name resolves to.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/f5ca4d78a721b8fd. Report an issue: GitHub.