apache/beam · error · ValueError

Parameter argv, if specified, must be a list. Received : %r

Error message

Parameter argv, if specified, must be a list. Received : %r

What it means

Pipeline.__init__ validates the argv/options parameter: when it is not a PipelineOptions instance it must be a list of command-line argument strings (e.g. sys.argv[1:]) so it can be parsed; the received object is neither.

Solutions

  1. Wrap flags in a list: argv=['--project=my-project'].
  2. Split a string with shlex.split before passing as argv.
  3. Alternatively pass PipelineOptions(shlex.split(flags_str)) via options=.

Example fix

# before
p = Pipeline(argv='--project=my-project --runner=DirectRunner')
# after
import shlex
p = Pipeline(argv=shlex.split('--project=my-project --runner=DirectRunner'))
Defensive patterns

Strategy: type-guard

Validate before calling

if isinstance(argv, str): argv = shlex.split(argv)

Type guard

def is_argv_list(v) -> bool:
    return v is None or (isinstance(v, list) and all(isinstance(x, str) for x in v))

Try / catch

try:
    p = Pipeline(argv=argv)
except ValueError as e:
    p = Pipeline(argv=shlex.split(argv))

Prevention

When it happens

Trigger: Pipeline(runner, argv='--project=my-project') — passing a single flag string instead of a list, or passing a dict as argv.

Common situations: Passing sys.argv (list, fine) vs a hand-written flag string, or copying examples that pass a string literal of flags.

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


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

Appendix: source

Thrown at sdks/python/apache_beam/pipeline.py:188

      if isinstance(options, PipelineOptions):
        # Make a deep copy of options since they could be overwritten in later
        # steps. However, the 'runner' object within 'options' is excluded from
        # the deep copy (it is shallow copied) due to potential issues with deep
        # copying specific runner instances, such as FlumeRunner.
        saved_runner = options.view_as(StandardOptions).runner
        options.view_as(StandardOptions).runner = None
        self._options = copy.deepcopy(options)
        self._options.view_as(StandardOptions).runner = saved_runner
        options.view_as(StandardOptions).runner = saved_runner
      else:
        raise ValueError(
            'Parameter options, if specified, must be of type PipelineOptions. '
            'Received : %r' % options)
    elif argv is not None:
      if isinstance(argv, list):
        self._options = PipelineOptions(argv)
      else:
        raise ValueError(
            'Parameter argv, if specified, must be a list. Received : %r' %
            argv)
    else:
      self._options = PipelineOptions([])

    FileSystems.set_options(self._options)

    if runner is None:
      runner = self._options.view_as(StandardOptions).runner
      if runner is None:
        runner = StandardOptions.DEFAULT_RUNNER
        logging.info((
            'Missing pipeline option (runner). Executing pipeline '
            'using the default runner: %s.'),
                     runner)

    if isinstance(runner, str):
      runner = create_runner(runner)

View on GitHub (pinned to 12126d8942)