{"record":{"id":"948f76c37986bfa9","repo":"apache/beam","slug":"class-s-does-not-implement-pipelinerunner-supported-pipeline","errorCode":null,"errorMessage":"Class '%s' does not implement PipelineRunner. Supported pipeline runners %s","messagePattern":"Class '(.+?)' does not implement PipelineRunner\\. Supported pipeline runners (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java","lineNumber":1924,"sourceCode":"          }\n        }\n        Method method = propertyNamesToGetters.get(entry.getKey());\n        // Only allow empty argument values for String, String Array, and\n        // Collection<String>.\n        Class<?> returnType = method.getReturnType();\n        JavaType type = MAPPER.getTypeFactory().constructType(method.getGenericReturnType());\n\n        if (\"runner\".equals(entry.getKey())) {\n          String runner = Iterables.getOnlyElement(entry.getValue());\n          final Map<String, Class<? extends PipelineRunner<?>>> pipelineRunners =\n              cache.supportedPipelineRunners;\n          if (pipelineRunners.containsKey(runner.toLowerCase())) {\n            convertedOptions.put(\"runner\", pipelineRunners.get(runner.toLowerCase(ROOT)));\n          } else {\n            try {\n              Class<?> runnerClass = Class.forName(runner, true, ReflectHelpers.findClassLoader());\n              if (!PipelineRunner.class.isAssignableFrom(runnerClass)) {\n                throw new IllegalArgumentException(\n                    String.format(\n                        \"Class '%s' does not implement PipelineRunner. \"\n                            + \"Supported pipeline runners %s\",\n                        runner, cache.getSupportedRunners()));\n              }\n              convertedOptions.put(\"runner\", runnerClass);\n            } catch (ClassNotFoundException e) {\n              String msg =\n                  String.format(\n                      \"Unknown 'runner' specified '%s', supported pipeline runners %s\",\n                      runner, cache.getSupportedRunners());\n              throw new IllegalArgumentException(msg, e);\n            }\n          }\n        } else if (isCollectionOrArrayOfAllowedTypes(returnType, type)) {\n          // Split any strings with \",\"\n          List<String> values =\n              entry.getValue().stream()","sourceCodeStart":1906,"sourceCodeEnd":1942,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/options/PipelineOptionsFactory.java#L1906-L1942","documentation":"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.","triggerScenarios":"Passing --runner=com.example.MyRunner (or a runner map entry) where the class exists on the classpath but is not a PipelineRunner subclass.","commonSituations":"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.","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"],"exampleFix":"// before\n--runner=org.apache.beam.sdk.options.PipelineOptions\n// after\n--runner=org.apache.beam.runners.direct.DirectRunner","handlingStrategy":"validation","validationCode":"Class<?> c = Class.forName(runnerClass);\nif (!PipelineRunner.class.isAssignableFrom(c)) throw new IllegalArgumentException(runnerClass + \" is not a PipelineRunner\");","typeGuard":null,"tryCatchPattern":"try { factory.fromArgs(args).create(); } catch (IllegalArgumentException e) { /* fall back to DirectRunner */ }","preventionTips":["Use registered short names (DirectRunner, DataflowRunner) instead of raw class names","Verify the class hierarchy of custom runners extends PipelineRunner"],"tags":["java","apache-beam","runner","classpath","pipeline-options"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}