apache/beam · critical · IllegalArgumentException

Cannot call #run(Pipeline) on an instance of

Error message

Cannot call #run(Pipeline) on an instance of %s. %s should only be used as the default to construct a Pipeline using %s, and cannot execute Pipelines. Instead, specify a %s by providing PipelineOptions in the system property '%s'.

What it means

CrashingRunner is Beam's default PipelineRunner that exists only to fail fast: any attempt to actually run a Pipeline throws this IllegalArgumentException. It indicates that no real runner (DirectRunner, FlinkRunner, DataflowRunner, ...) was configured, so PipelineOptions still carries the default CrashingRunner.

Solutions

  1. Set a real runner via PipelineOptions, e.g. `--runner=DirectRunner` or System property `-Drunner=DirectRunner`
  2. In code: `PipelineOptions opts = PipelineOptionsFactory.fromArgs(args).create(); opts.setRunner(DirectRunner.class);`
  3. If the pipeline is only meant for graph construction, do not call run(); use Pipeline.apply/merge only or GraphSurgeon-style tools

Example fix

// before
Pipeline p = Pipeline.create(PipelineOptionsFactory.create());
p.run();
// after
PipelineOptions opts = PipelineOptionsFactory.fromArgs("--runner=DirectRunner").create();
Pipeline p = Pipeline.create(opts);
p.run().waitUntilFinish();
Defensive patterns

Strategy: validation

Validate before calling

if (PipelineOptionsFactory.create().getRunner().equals(CrashingRunner.class)) {
  throw new IllegalStateException("No real runner configured; pass --runner=<Runner> or -Drunner=");
}

Type guard

boolean hasRealRunner(PipelineOptions opts) {
  return opts.getRunner() != null && !CrashingRunner.class.equals(opts.getRunner());
}

Try / catch

try {
  pipeline.run().waitUntilFinish();
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("CrashingRunner")) {
    throw new IllegalStateException("Configure a real runner, e.g. --runner=DirectRunner", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling Pipeline.run() (which delegates to CrashingRunner.run) without setting a real runner — i.e. no `--runner=` option and no `PipelineOptionsFactory`-registered runner; or explicitly instantiating CrashingRunner and calling run(Pipeline).

Common situations: Running a Beam job from an IDE or test harness without passing the `runner` system property; building a pipeline for serialization/inspection only and forgetting to swap in a real runner before execution; CI environments missing the runner option.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/7639f719253cabaa. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/testing/CrashingRunner.java:38

import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.sdk.PipelineRunner;
import org.apache.beam.sdk.options.PipelineOptions;

/**
 * A {@link PipelineRunner} that applies no overrides and throws an exception on calls to {@link
 * Pipeline#run()}. For use in {@link TestPipeline} to construct but not execute pipelines.
 */
public final class CrashingRunner extends PipelineRunner<PipelineResult> {

  @SuppressWarnings("unused") // used by reflection
  public static CrashingRunner fromOptions(PipelineOptions opts) {
    return new CrashingRunner();
  }

  @Override
  public PipelineResult run(Pipeline pipeline) {
    throw new IllegalArgumentException(
        String.format(
            "Cannot call #run(Pipeline) on an instance "
                + "of %s. %s should only be used as the default to construct a Pipeline "
                + "using %s, and cannot execute Pipelines. Instead, specify a %s "
                + "by providing PipelineOptions in the system property '%s'.",
            CrashingRunner.class.getSimpleName(),
            CrashingRunner.class.getSimpleName(),
            TestPipeline.class.getSimpleName(),
            PipelineRunner.class.getSimpleName(),
            TestPipeline.PROPERTY_BEAM_TEST_PIPELINE_OPTIONS));
  }
}

View on GitHub (pinned to 12126d8942)