apache/beam · error · java.lang.IllegalArgumentException
Could not instantiate class
Error message
Could not instantiate class
What it means
The expansion service tried to load and instantiate the user-supplied transform class via reflection but failed. It wraps ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException, or IllegalArgumentException thrown during Class.forName(...) and newInstance() in getTransform. This means the class could not be found on the expansion service classpath or could not be constructed with a no-arg constructor.
Solutions
- Add the JAR containing the transform class to the expansion service classpath (build a custom expansion service that includes your transform dependency).
- Verify the fully-qualified class name in the expansion request is correct and matches the deployed artifact version.
- Ensure the class is public, concrete (not abstract/interface), and has an accessible no-arg constructor.
- Check the wrapped cause ('Caused by') in the exception to distinguish ClassNotFoundException vs constructor failure and fix accordingly.
Example fix
// before: running stock expansion service java -jar beam-expansion-service.jar // after: shadow JAR that bundles your transform ./gradlew shadowJar && java -jar my-expansion-service.jar # includes mytransforms dependency
Defensive patterns
Strategy: try-catch
Validate before calling
Class<?> c;
try { c = Class.forName(fqcn); } catch (ClassNotFoundException e) { throw new IllegalStateException("Transform not on expansion service classpath: " + fqcn); }
if (c.isInterface() || java.lang.reflect.Modifier.isAbstract(c.getModifiers())) throw new IllegalStateException("Transform must be concrete");
try { c.getDeclaredConstructor().setAccessible(true); } catch (NoSuchMethodException e) { throw new IllegalStateException("Transform lacks a no-arg constructor"); } Type guard
function canInstantiate(fqcn) {
try { const c = java.lang.Class.forName(fqcn);
return !c.isInterface() && !java.lang.reflect.Modifier.isAbstract(c.getModifiers()) && c.getConstructor();
} catch (e) { return false; }
} Try / catch
try {
PTransform<PInput, POutput> t = provider.getTransform(payload);
} catch (IllegalArgumentException e) {
log.error("Transform instantiation failed: {}", e.getMessage(), e.getCause()); // inspect 'Caused by' for ClassNotFoundException vs ctor failure
throw new ExpansionSetupException(fqcn + " missing or not instantiable on service classpath", e);
} Prevention
- Build a dedicated expansion service fat JAR that bundles every custom transform dependency.
- Add a startup smoke test that Class.forName()s each transform identifier the service is expected to serve.
- Keep the transform class public, concrete, with an explicit public no-arg constructor.
- Pin the same artifact version for the pipeline SDK and the expansion service.
When it happens
Trigger: Calling ExpansionService / expand with a transform identifier whose class is absent from the service's classpath; the class is abstract, an interface, or lacks an accessible no-arg constructor; the class's constructor throws an exception; or a security/visibility issue blocks reflective access.
Common situations: Deploying a pipeline against a stock Beam expansion service JAR without bundling the custom transform's JAR; typos or wrong fully-qualified class names in pipeline payloads; fat-jar shading excluding the transform; class constructor performing DI or throwing at init time.
Related errors
- Could not find a matching method in transform for…
- Could not find class
- Could not find class:
- Could not find class
- Could not invoke the builder method on transform with…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/b1a546eabd30ec9f.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java:137
constructorRow,
constructor.getGenericParameterTypes());
transform = (PTransform<PInput, POutput>) constructor.newInstance(parameterValues);
} else {
Method[] methods = transformClass.getMethods();
Method method = findMappingConstructorMethod(methods, payload, allowlistClass);
Object[] parameterValues =
getParameterValues(
method.getParameters(), constructorRow, method.getGenericParameterTypes());
transform = (PTransform<PInput, POutput>) method.invoke(null /* static */, parameterValues);
}
return applyBuilderMethods(transform, payload, allowlistClass);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Could not find class " + className, e);
} catch (InstantiationException
| IllegalArgumentException
| IllegalAccessException
| InvocationTargetException e) {
throw new IllegalArgumentException("Could not instantiate class " + className, e);
}
}
@SuppressWarnings("assignment")
private PTransform<PInput, POutput> applyBuilderMethods(
PTransform<PInput, POutput> transform,
JavaClassLookupPayload payload,
AllowedClass allowListClass) {
for (BuilderMethod builderMethod : payload.getBuilderMethodsList()) {
Method method = getMethod(transform, builderMethod, allowListClass);
try {
Row builderMethodRow = decodeRow(builderMethod.getSchema(), builderMethod.getPayload());
transform =
(PTransform<PInput, POutput>)
method.invoke(
transform,
getParameterValues(
method.getParameters(),View on GitHub (pinned to 12126d8942)