{"record":{"id":"eea5aebd272b89fe","repo":"apache/beam","slug":"returning-a-s-from-a-pardo-or-flatmap-is-discouraged-please","errorCode":null,"errorMessage":"Returning a %s from a ParDo or FlatMap is discouraged. Please use list(\"%s\") if you really want this behavior.","messagePattern":"Returning a (.+?) from a ParDo or FlatMap is discouraged\\. Please use list\\(\"(.+?)\"\\) if you really want this behavior\\.","errorType":"validation","errorClass":"TypeCheckError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/typehints/typecheck.py","lineNumber":113,"sourceCode":"      result = method(*args, **kwargs)\n    except TypeCheckError as e:\n      # TODO(BEAM-10710): Remove the 'ParDo' prefix for the label name\n      error_msg = (\n          'Runtime type violation detected within ParDo(%s): '\n          '%s' % (self.full_label, e))\n      _, _, tb = sys.exc_info()\n      raise TypeCheckError(error_msg).with_traceback(tb)\n    else:\n      return self._check_type(result)\n\n  @staticmethod\n  def _check_type(output):\n    if output is None:\n      return output\n\n    elif isinstance(output, (dict, bytes, str)):\n      object_type = type(output).__name__\n      raise TypeCheckError(\n          'Returning a %s from a ParDo or FlatMap is '\n          'discouraged. Please use list(\"%s\") if you really '\n          'want this behavior.' % (object_type, output))\n    elif not isinstance(output, abc.Iterable):\n      raise TypeCheckError(\n          'FlatMap and ParDo must return an '\n          'iterable. %s was returned instead.' % type(output))\n    return output\n\n\nclass TypeCheckWrapperDoFn(AbstractDoFnWrapper):\n  \"\"\"A wrapper around a DoFn which performs type-checking of input and output.\n  \"\"\"\n  def __init__(self, dofn, type_hints, label=None):\n    super().__init__(dofn)\n    self._process_fn = self.dofn._process_argspec_fn()\n    if type_hints.input_types:\n      input_args, input_kwargs = type_hints.input_types","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/typehints/typecheck.py#L95-L131","documentation":"Beam's _check_type rejects a DoFn/FlatMap callable returning a dict, bytes, or str directly. Iterating such a return value would yield keys/characters rather than records, which is almost always a bug, so Beam raises TypeCheckError to force the user to be explicit.","triggerScenarios":"A FlatMap/ParDo function returns a string, bytes, or dict (e.g. 'return s' instead of yielding, or returning a dict expecting it to be one record).","commonSituations":"Returning a JSON string from a FlatMap intending a single element; returning a dict as one output record; accidentally returning input unchanged when input is a string.","solutions":["Wrap the value in a list: return [my_string] / [my_dict].","Convert to a generator: yield the value instead of returning it.","If you truly want per-character/key iteration, use list(value) as the message suggests.","Use beam.Map instead of FlatMap when emitting exactly one element per input."],"exampleFix":"// before\ndef expand(x):\n    return x['payload']  # a str\n// after\ndef expand(x):\n    return [x['payload']]","handlingStrategy":"validation","validationCode":"def safe_flatmap(fn):\n    def wrapped(x):\n        out = fn(x)\n        if isinstance(out, (str, bytes, dict)):\n            return [out]\n        return out\n    return wrapped","typeGuard":"def returns_element_list(out) -> bool:\n    return out is None or (isinstance(out, list) and not isinstance(out, (str, bytes, dict)))","tryCatchPattern":"try:\n    out = fn(x)\nexcept TypeCheckError as e:\n    log.error('FlatMap returned bad value: %s', e)\n    return []","preventionTips":["Return [value] or use yield in FlatMap callables","Prefer beam.Map for one-output-per-input transforms","Unit test DoFn callables against known inputs before wiring into pipelines"],"tags":["python","apache-beam","flatmap","return-type"],"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-20T03:17:13.778Z"}