{"record":{"id":"6c46cc89eeac2e1b","repo":"apache/beam","slug":"an-option-type-hint-only-accepts-a-single-type-parameter","errorCode":null,"errorMessage":"An Option type-hint only accepts a single type parameter.","messagePattern":"An Option type-hint only accepts a single type parameter\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/typehints/typehints.py","lineNumber":632,"sourceCode":"      except (TypeError, KeyError):\n        # Not a union of compatible schema types.\n        pass\n\n    return self.UnionConstraint(params)\n\n\nUnionConstraint = UnionHint.UnionConstraint\n\n\nclass OptionalHint(UnionHint):\n  \"\"\"An Option type-hint. Optional[X] accepts instances of X or None.\n\n  The Optional[X] factory function proxies to Union[X, type(None)]\n  \"\"\"\n  def __getitem__(self, py_type):\n    # A single type must have been passed.\n    if isinstance(py_type, abc.Sequence):\n      raise TypeError(\n          'An Option type-hint only accepts a single type '\n          'parameter.')\n\n    return Union[py_type, type(None)]\n\n\ndef is_nullable(typehint):\n  return (\n      isinstance(typehint, UnionConstraint) and\n      typehint.contains_type(type(None)) and\n      len(list(typehint.inner_types())) == 2)\n\n\ndef get_concrete_type_from_nullable(typehint):\n  if is_nullable(typehint):\n    for inner_type in typehint.inner_types():\n      if not type(None) == inner_type:\n        return inner_type","sourceCodeStart":614,"sourceCodeEnd":650,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/typehints/typehints.py#L614-L650","documentation":"OptionalHint.__getitem__ raises TypeError('An Option type-hint only accepts a single type parameter.') when Optional[...] is subscripted with a sequence of multiple types. Beam's Optional[X] proxies to Union[X, type(None)] and therefore only accepts exactly one inner type.","triggerScenarios":"Writing Optional[int, str] or Optional[List[int], Dict[str, int]] — passing a Sequence to the Optional hint factory instead of one type.","commonSituations":"Developers assuming Optional behaves like Union (as typing.Optional[X, Y] would error in typing too); mistakenly trying to express 'optional union' as Optional[A, B]; copy-paste from Union definitions.","solutions":["Nest the union inside a single parameter: Optional[Union[int, str]].","Use Union[int, str, type(None)] directly if you prefer an explicit union with None.","Verify only one type argument is passed when constructing Optional hints.","Fix hint-building code to wrap multiple types in Union before applying Optional."],"exampleFix":"# before\nOptional[int, str]\n# after\nOptional[Union[int, str]]","handlingStrategy":"validation","validationCode":"def make_optional(ts):\n    if isinstance(ts, (list, tuple)):\n        return Optional[Union[tuple(ts)]] if len(ts) > 1 else Optional[ts[0]]\n    return Optional[ts]","typeGuard":"def is_single_type(x):\n    return not isinstance(x, (list, tuple))","tryCatchPattern":"try:\n    hint = Optional[py_type]\nexcept TypeError as e:\n    if 'only accepts a single type' in str(e):\n        hint = Optional[Union[tuple(py_type)]]\n    else:\n        raise","preventionTips":["Wrap multiple types in Union before applying Optional","Never subscript Optional with a list/tuple of types","Mirror typing.Optional semantics: exactly one parameter"],"tags":["python","apache-beam","typehints","optional"],"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"}