OpenAPITools/openapi-generator · error · GeneratorNotFoundException
Can't instantiate config class with name '{name}'. The class
Error message
Can't instantiate config class with name '{name}'. The class was found but could not be constructed; it must implement CodegenConfig, declare a public no-argument constructor, and that constructor must not throw.
Available:
{availableConfigs} What it means
Thrown by CodegenConfigLoader.forName(String) (called by CodegenConfigurator and the CLI's -g/--generator-name option) when the requested generator class WAS found on the classpath but could not be constructed. The exact branch is the catch of ReflectiveOperationException | ClassCastException around 'loadConfigClass(name).asSubclass(CodegenConfig.class).getDeclaredConstructor().newInstance()'. So either the class does not implement CodegenConfig (ClassCastException from asSubclass), has no public no-argument constructor (NoSuchMethodException), is not accessible (IllegalAccessException), or its constructor threw (InvocationTargetException). The message appends the list of available config names so you can pick a valid generator name.
Source
Thrown at modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfigLoader.java:74
// else try to load directly
try {
return loadConfigClass(name).asSubclass(CodegenConfig.class).getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException e) {
throw generatorNotFoundException(name, availableConfigs, e);
} catch (NoClassDefFoundError e) {
if (e.getCause() instanceof ExceptionInInitializerError || hasInitializationFailed(name)) {
throw generatorInitializationException(name, availableConfigs, e);
}
throw generatorNotFoundException(name, availableConfigs, e);
} catch (UnsupportedClassVersionError e) {
throw generatorIncompatibleException(name, availableConfigs, e);
} catch (ExceptionInInitializerError e) {
throw generatorInitializationException(name, availableConfigs, e);
} catch (LinkageError e) {
throw generatorLinkageException(name, availableConfigs, e);
} catch (ReflectiveOperationException | ClassCastException e) {
throw new GeneratorNotFoundException(
"Can't instantiate config class with name '" + name + "'. The class was found but could not be "
+ "constructed; it must implement CodegenConfig, declare a public no-argument constructor, "
+ "and that constructor must not throw.\nAvailable:\n" + availableConfigs, e);
} finally {
LOADING_CLASS_LOADER.remove();
}
}
public static List<CodegenConfig> getAll() {
List<CodegenConfig> output = new ArrayList<CodegenConfig>();
Set<String> configClasses = new HashSet<String>();
for (ClassLoader classLoader : getConfigClassLoaders()) {
ServiceLoader<CodegenConfig> loader = ServiceLoader.load(CodegenConfig.class, classLoader);
Iterator<ServiceLoader.Provider<CodegenConfig>> providers = loader.stream().iterator();
while (true) {
ServiceLoader.Provider<CodegenConfig> provider;
// Per-entry failures (missing/invalid provider class, LinkageError) happen after the
// cursor advances, so skip them and keep discovering. A resource-location failureView on GitHub (pinned to fcec517be3)
Solutions
- Read the 'Available:' list in the message and use one of those exact generator names for -g; if the name you wanted is absent, your class is not on the classpath at all (different error branch).
- If it is a custom generator: make the class public and top-level (or public static nested), implement CodegenConfig (normally by extending DefaultCodegen), and declare an explicit public no-argument constructor.
- Inspect the chained cause in the stack trace: NoSuchMethodException => add a public no-arg constructor; IllegalAccessException => make the class/constructor public; InvocationTargetException => fix the exception the constructor itself threw (it is the innermost Caused by).
- Rebuild and run the custom generator against the same openapi-generator version (mvn dependency the generator against the matching modules/openapi-generator artifact) to eliminate ClassCastException and AbstractMethodError from API drift.
- If packaging a shaded jar, verify exactly one copy of the generator class and its dependencies exists (jar tf | grep <ClassName>) and remove stale duplicates.
Example fix
// before
class MyJavaGenerator extends DefaultCodegen {
public MyJavaGenerator(String specVersion) { ... }
}
// after
public class MyJavaGenerator extends DefaultCodegen {
public MyJavaGenerator() { ... } // public, no-arg, must not throw
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight a generator name before CodegenConfigLoader.forName(name)
Class<?> clazz;
try {
clazz = Class.forName(name, false, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Generator class not on classpath: " + name, e);
}
if (!org.openapitools.codegen.CodegenConfig.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException(name + " does not implement CodegenConfig");
}
try {
java.lang.reflect.Constructor<?> ctor = clazz.getDeclaredConstructor();
if (!java.lang.reflect.Modifier.isPublic(clazz.getModifiers())
|| !java.lang.reflect.Modifier.isPublic(ctor.getModifiers())) {
throw new IllegalArgumentException(name + " and its no-arg constructor must be public");
}
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(name + " lacks a public no-arg constructor", e);
} Type guard
private static boolean isInstantiableGenerator(Class<?> c) {
return org.openapitools.codegen.CodegenConfig.class.isAssignableFrom(c)
&& !Modifier.isAbstract(c.getModifiers())
&& Modifier.isPublic(c.getModifiers());
} Try / catch
try {
CodegenConfig config = CodegenConfigLoader.forName(generatorName);
} catch (RuntimeException e) {
// Distinguish wrapper vs cause: NoSuchMethodException => missing ctor,
// InvocationTargetException => ctor threw (unwrap getCause()).
Throwable root = Stream.iterate(e, Throwable::getCause)
.takeWhile(Objects::nonNull).reduce((a, b) -> b).orElse(e);
log.error("Generator '{}' failed to instantiate: {} - check Available list in message",
generatorName, root);
throw e;
} Prevention
- Smoke-test custom generators in CI: one test that calls CodegenConfigLoader.forName('yourGenerator') and asserts a non-null instance.
- Pin the openapi-generator version used to compile and run custom generators to the same coordinate.
- Run 'openapi-generator-cli list' after any dependency change to confirm custom generators are discoverable.
When it happens
Trigger: Passing -g <name> (or calling CodegenConfigLoader.forName(name)) where <name> resolves to a class that: (a) is not a CodegenConfig implementation (asSubclass throws ClassCastException), (b) only declares parameterized constructors so no public no-arg constructor exists, (c) is abstract or non-public, or (d) whose no-arg constructor throws (missing resource, NPE in field init). Note the sibling branches in the same try block produce DIFFERENT messages: ExceptionInInitializerError/NoClassDefFoundError-with-init-cause -> initialization error, UnsupportedClassVersionError -> incompatible, other LinkageError -> linkage, ClassNotFoundException -> GeneratorNotFound. This message appears only for reflective instantiation failure or wrong type.
Common situations: Writing a custom generator as a non-public or inner class; giving the custom generator only a constructor with arguments; a custom generator whose constructor reads a bundled resource or registers type mappings and throws when they are absent; compiling the generator against a different openapi-generator version than the one on the runtime classpath (changed supertypes -> ClassCastException); duplicate stale copies of the class in a shaded/uber jar; a typo'd generator name that accidentally matches another class on the classpath.
Related errors
- Failed to load custom NORMALIZER_CLASS '{className}'. This c
- Failed to instantiate custom NORMALIZER_CLASS '{className}'.
- Unable to locate /java-helidon/common/Status.java to discove
- Issues with the OpenAPI input. Possible causes: invalid/miss
- missing config!
AI-assisted analysis of OpenAPITools/openapi-generator@fcec517be3 (2026-08-22).
Data as JSON: /api/errors/dcc22814b46ff0f8.
Report an issue: GitHub.