apache/beam · error · TypeCheckError

FlatMap and ParDo must return an iterable.

Error message

FlatMap and ParDo must return an iterable. %s was returned instead.

What it means

Beam requires FlatMap/ParDo callables to return an iterable of output elements. _check_type raises TypeCheckError when the returned value is not iterable (after excluding None). This guarantees the runner can iterate the function's outputs.

Solutions

  1. Return a list/generator: return [result].
  2. Use beam.Map (or ParDo with a DoFn yielding one element) when there is exactly one output per input.
  3. Make the returned object iterable (implement __iter__) if it is a custom container.
  4. Yield outputs instead of returning a single value.

Example fix

// before
p | beam.FlatMap(lambda x: x * 2)  # returns int
// after
p | beam.Map(lambda x: x * 2)
Defensive patterns

Strategy: validation

Validate before calling

from collections.abc import Iterable
def ensure_iterable(out):
    if out is None:
        return []
    if not isinstance(out, Iterable):
        return [out]
    return out

Type guard

def is_iterable_output(out) -> bool:
    return out is None or isinstance(out, Iterable)

Try / catch

try:
    outputs = fn(element)
except TypeCheckError:
    outputs = [fn(element)] if not isinstance(fn(element), Iterable) else []

Prevention

When it happens

Trigger: A FlatMap function returns a non-iterable such as an int, a custom object, or a single record object instead of a list/generator of records.

Common situations: Mixing up Map vs FlatMap semantics; a function that forgot to wrap its result in a list; returning a custom class that doesn't implement __iter__.

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


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

Appendix: source

Thrown at sdks/python/apache_beam/typehints/typecheck.py:118

          '%s' % (self.full_label, e))
      _, _, tb = sys.exc_info()
      raise TypeCheckError(error_msg).with_traceback(tb)
    else:
      return self._check_type(result)

  @staticmethod
  def _check_type(output):
    if output is None:
      return output

    elif isinstance(output, (dict, bytes, str)):
      object_type = type(output).__name__
      raise TypeCheckError(
          'Returning a %s from a ParDo or FlatMap is '
          'discouraged. Please use list("%s") if you really '
          'want this behavior.' % (object_type, output))
    elif not isinstance(output, abc.Iterable):
      raise TypeCheckError(
          'FlatMap and ParDo must return an '
          'iterable. %s was returned instead.' % type(output))
    return output


class TypeCheckWrapperDoFn(AbstractDoFnWrapper):
  """A wrapper around a DoFn which performs type-checking of input and output.
  """
  def __init__(self, dofn, type_hints, label=None):
    super().__init__(dofn)
    self._process_fn = self.dofn._process_argspec_fn()
    if type_hints.input_types:
      input_args, input_kwargs = type_hints.input_types
      self._input_hints = getcallargs_forhints(
          self._process_fn, *input_args, **input_kwargs)
    else:
      self._input_hints = None
    # TODO(robertwb): Multi-output.

View on GitHub (pinned to 12126d8942)