quarkusio/quarkus · error · IllegalArgumentException

%s does not implement %s

Error message

%s does not implement %s

What it means

checkExtensionPoints validates each configured Quartz extension point (JobListener, TriggerListener, etc.) by loading its class and checking that it is assignable from the required interface/parent class. If the class exists but does not implement the required type, an IllegalArgumentException stating '<class> does not implement <type>' is thrown at build time.

Source

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

            if (m.getMethod().hasAnnotation(NONCONCURRENT)) {
                nonconcurrentMethods.add(m.getMethod().declaringClass().name() + "#" + m.getMethod().name());
            }
        }

        syntheticBeanBuildItemBuildProducer.produce(SyntheticBeanBuildItem.configure(QuartzSupport.class)
                .scope(Singleton.class) // this should be @ApplicationScoped but it fails for some reason
                .setRuntimeInit()
                .supplier(recorder.quartzSupportSupplier(driverDialect.getDriver(), driverDialect.getDataSources(),
                        nonconcurrentMethods))
                .done());
    }

    private static void checkExtensionPoints(Map<String, QuartzExtensionPointConfig> config, Class<?> clazz) {
        for (QuartzExtensionPointConfig extensionPointConfig : config.values()) {
            try {
                if (!clazz.isAssignableFrom(
                        Class.forName(extensionPointConfig.clazz(), false, Thread.currentThread().getContextClassLoader()))) {
                    throw new IllegalArgumentException(
                            String.format("%s does not implement %s", extensionPointConfig.clazz(), clazz));
                }
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException(e);
            }
        }
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the configured class implement/extend the required Quartz SPI type (e.g. org.quartz.JobListener).
  2. Check you put the class under the correct config section for its actual type.
  3. Verify against the Quartz API for the version on the classpath — interface names may differ across versions.

Example fix

// before
public class MyListener { /* no interface */ }

// after
public class MyListener implements org.quartz.JobListener { ... }
Defensive patterns

Strategy: validation

Validate before calling

// before referencing in config, verify the SPI contract
Class<?> c = Class.forName("com.myapp.MyListener", false,
        Thread.currentThread().getContextClassLoader());
if (!org.quartz.JobListener.class.isAssignableFrom(c)) {
    throw new IllegalStateException("configured listener must implement org.quartz.JobListener");
}

Prevention

When it happens

Trigger: Configure a class under quarkus.quartz.<extension-point> (e.g. job-listeners, store-classes) whose class loads successfully but does not extend/implement the required Quartz SPI type, e.g. a listener class that doesn't implement JobListener.

Common situations: Pointing a listener config at a plain class or wrong listener type (JobListener vs TriggerListener confusion); implementing the wrong interface after a refactor; copying config between properties of different extension point kinds.

Related errors


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