apache/druid · error · IllegalStateException

Unknown module type [ ]

Error message

Unknown module type [%s]

What it means

DruidInjectorBuilder.addInput accepts either a Module instance or a Class and dispatches to addModule/addClass. Any other input type is rejected with this ISE because the injector builder cannot interpret it.

Solutions

  1. Pass a Module instance (e.g. new MyModule()) or a Class implementing Module
  2. Unroll collections: call addInput per module instead of passing the list
  3. Use Class.forName(...).asSubclass(Module.class) if starting from a class-name string

Example fix

// before
builder.addInput(modules); // List<Module>
// after
modules.forEach(builder::addInput);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(input instanceof Module) && !(input instanceof Class)) {
  throw new IllegalArgumentException("addInput expects Module or Class");
}

Type guard

static boolean isValidInjectorInput(Object o) {
  return o instanceof Module || o instanceof Class;
}

Try / catch

try {
  builder.addInput(input);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Unknown module type")) {
    log.error("Pass a Module instance or Module class, got: " + input.getClass());
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling injectorBuilder.addInput(obj) with an object that is neither a Module nor a Class (e.g. a List of modules, a String class name, or a Provider).

Common situations: Passing a collection of modules instead of iterating; reflection code passing a Class<?> that was loaded as the wrong type; tests (testBadModule/testBadModuleClass) exercising bad input.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/cfb0790444ebaf7d. Report an issue: GitHub.

Appendix: source

Thrown at server/src/main/java/org/apache/druid/guice/DruidInjectorBuilder.java:142

    return this;
  }

  /**
   * Add an arbitrary {@link Module}, {@link DruidModule} instance,
   * or a subclass of these classes. If a class is provided, it is instantiated
   * using the base injector to allow dependency injection. If a module
   * instance is provided, its members are injected. Note that such
   * modules have visibility <i>only</i> to objects defined in the base
   * injector, but not to objects defined in the injector being built.
   */
  public DruidInjectorBuilder addInput(Object input)
  {
    if (input instanceof Module) {
      return addModule((Module) input);
    } else if (input instanceof Class) {
      return addClass((Class<?>) input);
    } else {
      throw new ISE("Unknown module type [%s]", input.getClass());
    }
  }

  public DruidInjectorBuilder addModule(Module module)
  {
    if (!acceptModule(module.getClass())) {
      return this;
    }
    baseInjector.injectMembers(module);
    if (module instanceof DruidModule) {
      registerJacksonModules((DruidModule) module);
    }
    modules.add(module);
    return this;
  }

  public DruidInjectorBuilder addClass(Class<?> input)
  {

View on GitHub (pinned to 9b90983fd2)