apache/beam · error · IllegalArgumentException
Class ' ' does not implement PipelineRunner. Supported…
Error message
Class '%s' does not implement PipelineRunner. Supported pipeline runners %s
What it means
The 'runner' option value named a class that loads successfully but does not extend PipelineRunner. Beam validates the loaded Class with Class.forName and isAssignableFrom before using it, throwing IllegalArgumentException with the list of supported runners.
Solutions
- Make the named class implement/extend PipelineRunner
- Set --runner to a known runner (DirectRunner, DataflowRunner, FlinkRunner, SparkRunner) or its registered short name
- Verify the fully-qualified class name corresponds to an actual runner class
Example fix
// before --runner=org.apache.beam.sdk.options.PipelineOptions // after --runner=org.apache.beam.runners.direct.DirectRunner
Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = Class.forName(runnerClass); if (!PipelineRunner.class.isAssignableFrom(c)) throw new IllegalArgumentException(runnerClass + " is not a PipelineRunner");
Try / catch
try { factory.fromArgs(args).create(); } catch (IllegalArgumentException e) { /* fall back to DirectRunner */ } Prevention
- Use registered short names (DirectRunner, DataflowRunner) instead of raw class names
- Verify the class hierarchy of custom runners extends PipelineRunner
When it happens
Trigger: Passing --runner=com.example.MyRunner (or a runner map entry) where the class exists on the classpath but is not a PipelineRunner subclass.
Common situations: Pointing --runner at a PipelineOptions class or pipeline class by mistake; copying a class name from an unrelated project; refactoring moved the runner out of the PipelineRunner hierarchy.
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
- Unknown 'runner' specified
- All inherited interfaces of
- Attempted to invoke timer
- AutoValue generated class not found
- Class missing a property named ' '.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/948f76c37986bfa9.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java:1924
}
}
Method method = propertyNamesToGetters.get(entry.getKey());
// Only allow empty argument values for String, String Array, and
// Collection<String>.
Class<?> returnType = method.getReturnType();
JavaType type = MAPPER.getTypeFactory().constructType(method.getGenericReturnType());
if ("runner".equals(entry.getKey())) {
String runner = Iterables.getOnlyElement(entry.getValue());
final Map<String, Class<? extends PipelineRunner<?>>> pipelineRunners =
cache.supportedPipelineRunners;
if (pipelineRunners.containsKey(runner.toLowerCase())) {
convertedOptions.put("runner", pipelineRunners.get(runner.toLowerCase(ROOT)));
} else {
try {
Class<?> runnerClass = Class.forName(runner, true, ReflectHelpers.findClassLoader());
if (!PipelineRunner.class.isAssignableFrom(runnerClass)) {
throw new IllegalArgumentException(
String.format(
"Class '%s' does not implement PipelineRunner. "
+ "Supported pipeline runners %s",
runner, cache.getSupportedRunners()));
}
convertedOptions.put("runner", runnerClass);
} catch (ClassNotFoundException e) {
String msg =
String.format(
"Unknown 'runner' specified '%s', supported pipeline runners %s",
runner, cache.getSupportedRunners());
throw new IllegalArgumentException(msg, e);
}
}
} else if (isCollectionOrArrayOfAllowedTypes(returnType, type)) {
// Split any strings with ","
List<String> values =
entry.getValue().stream()View on GitHub (pinned to 12126d8942)