apache/beam · error · ValueError
Flags must be an iterable of of strings, not a single…
Error message
Flags must be an iterable of of strings, not a single string.
What it means
PipelineOptions.__init__ accepts flags as an iterable of strings; a single str technically passes Iterable[str] but iterates as characters, so it is explicitly rejected. The library raises ValueError to prevent almost-certainly unintended behavior.
Solutions
- Wrap the flags in a list: PipelineOptions(['--runner=DirectRunner']).
- If starting from a single string, split it: shlex.split(flags_str).
- Fix config parsing to always produce a list of strings.
Example fix
# before
options = PipelineOptions('--runner=DataflowRunner')
# after
import shlex
options = PipelineOptions(shlex.split('--runner=DataflowRunner')) Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(flags, str):
flags = shlex.split(flags) Type guard
def is_flag_list(v) -> bool:
return isinstance(v, (list, tuple)) and all(isinstance(x, str) for x in v) Try / catch
try:
opts = PipelineOptions(flags)
except ValueError as e:
opts = PipelineOptions(shlex.split(flags)) Prevention
- Always construct options from a list literal of flag strings.
- Add a lint/check helper that rejects str inputs to options-building code.
When it happens
Trigger: PipelineOptions('--runner=DirectRunner') — passing one flag as a bare string instead of a list.
Common situations: Hard-coding a single CLI flag in scripts, or building options from a string read from a config file without splitting it.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- A cluster_identifier should be Optional[Union[str…
- Cannot get a type descriptor for
- Cannot interpret as Duration.
- CombineGlobally can be used only with combineFn objects…
- database_config must be VectorDatabaseWriteConfig, got
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/98d1770fc794c11e.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/options/pipeline_options.py:369
flag names.
Option names: These are defined as dest in the
parser.add_argument() for each flag. Passing flags
like {no_use_public_ips: True}, for which the dest is
defined to a different flag name in the parser,
would be discarded. Instead, pass the dest of
the flag (dest of no_use_public_ips is use_public_ips).
"""
# Initializing logging configuration in case the user did not set it up.
logging.basicConfig()
# self._flags stores a list of not yet parsed arguments, typically,
# command-line flags. This list is shared across different views.
# See: view_as().
if isinstance(flags, str):
# Unfortunately a single str passes the Iterable[str] test, as it is
# an iterable of single characters. This is almost certainly not the
# intent...
raise ValueError(
"Flags must be an iterable of of strings, not a single string.")
self._flags = flags
# Build parser that will parse options recognized by the [sub]class of
# PipelineOptions whose object is being instantiated.
parser = _BeamArgumentParser(allow_abbrev=False)
for cls in type(self).mro():
if cls == PipelineOptions:
break
elif '_add_argparse_args' in cls.__dict__:
cls._add_argparse_args(parser) # type: ignore
# The _visible_options attribute will contain options that were recognized
# by the parser.
self._visible_options, _ = parser.parse_known_args(flags)
# self._all_options is initialized with overrides to flag values,
# provided in kwargs, and will store key-value pairs for options recognizedView on GitHub (pinned to 12126d8942)