apache/druid · error · IllegalStateException
Class [ ] does not implement
Error message
Class [%s] does not implement %s
What it means
DruidInjectorBuilder.addClass validates that the supplied Class implements com.google.inject.Module; if not, instantiation is impossible in the injector pipeline and an ISE is thrown naming the class and required interface.
Solutions
- Make the class implement Module (or extend DruidModule)
- Register a different class that actually implements Module
- If the class is a plain binding target, add it inside a module's configure() instead of addInput
Example fix
// before builder.addClass(MyConfig.class); // not a Module // after builder.addClass(MyConfigModule.class); // implements DruidModule
Defensive patterns
Strategy: type-guard
Validate before calling
if (!Module.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException(clazz + " does not implement Module");
} Type guard
static boolean isModuleClass(Class<?> c) {
return Module.class.isAssignableFrom(c);
} Try / catch
try {
builder.addClass(clazz);
} catch (IllegalStateException e) {
if (e.getMessage().contains("does not implement")) {
log.error("Class " + clazz + " must implement Module");
}
throw e;
} Prevention
- Have all registered modules implement DruidModule/Module
- Run a startup test that builds the injector from the full module list
- Grep initialization lists when removing `implements Module` from a class
When it happens
Trigger: Calling addInput(SomeClass.class) (leading to addClass) where SomeClass does not implement Module; addInput is its caller in the builder chain.
Common situations: Typos passing the wrong class (a config class instead of a module); refactors removing `implements Module` from a class still registered in initialization lists; tests registering non-module classes.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unknown module type [ ]
- AppenderatorsManager methods should only called by services…
- attempt to get boolean[] null vector from string[] only…
- attempt to get double[] from string[] only scalar binding
- attempt to get long[] from string[] only scalar binding
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/1d96ef1ebf254561.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/main/java/org/apache/druid/guice/DruidInjectorBuilder.java:174
return this;
}
public DruidInjectorBuilder addClass(Class<?> input)
{
if (!acceptModule(input)) {
return this;
}
if (DruidModule.class.isAssignableFrom(input)) {
@SuppressWarnings("unchecked")
DruidModule module = baseInjector.getInstance((Class<? extends DruidModule>) input);
registerJacksonModules(module);
modules.add(module);
} else if (Module.class.isAssignableFrom(input)) {
@SuppressWarnings("unchecked")
Module module = baseInjector.getInstance((Class<? extends Module>) input);
modules.add(module);
} else {
throw new ISE("Class [%s] does not implement %s", input, Module.class);
}
return this;
}
/**
* Filter module classes based on the (optional) module exclude list and
* (optional) set of known node roles.
*/
private boolean acceptModule(Class<?> moduleClass)
{
// Modules config is optional: it won't be present in tests or clients.
String moduleClassName = moduleClass.getName();
if (moduleClassName != null && modulesConfig.getExcludeList().contains(moduleClassName)) {
log.info("Not loading module %s because it is present in excludeList", moduleClassName);
return false;
}
// Tests don't have node roles, and so want to load the given modulesView on GitHub (pinned to 9b90983fd2)