{"record":{"id":"82a84c0d1facb076","repo":"apache/beam","slug":"typehint-is-not-of-nullable-type","errorCode":null,"errorMessage":"Typehint is not of nullable type","messagePattern":"Typehint is not of nullable type","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/typehints/typehints.py","lineNumber":652,"sourceCode":"          '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\n  else:\n    raise TypeError('Typehint is not of nullable type', typehint)\n\n\nclass TupleHint(CompositeTypeHint):\n  \"\"\"A Tuple type-hint.\n\n  Tuple can accept 1 or more type-hint parameters.\n\n  Tuple[X, Y] represents a tuple of *exactly* two elements, with the first\n  being of type 'X' and the second an instance of type 'Y'.\n\n    * (1, 2) satisfies Tuple[int, int]\n\n  Additionally, one is able to type-hint an arbitary length, homogeneous tuple\n  by passing the Ellipsis (...) object as the second parameter.\n\n  As an example, Tuple[str, ...] indicates a tuple of any length with each\n  element being an instance of 'str'.\n  \"\"\"","sourceCodeStart":634,"sourceCodeEnd":670,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/typehints/typehints.py#L634-L670","documentation":"get_concrete_type_from_nullable raises TypeError('Typehint is not of nullable type') when given a type hint that is not Optional/nullable (i.e. is_nullable(hint) is False). The helper is meant to unwrap Optional[T] into T and refuses non-nullable inputs rather than guessing.","triggerScenarios":"Calling get_concrete_type_from_nullable on a plain type like int, a Union without NoneType, or any non-Optional hint; helper misuse in code that assumes all incoming hints may be Optional.","commonSituations":"Pipeline framework code that unwraps optionality before applying conversions but receives raw hints; refactors where a hint stopped being Optional (e.g. Optional[str] changed to str) but the unwrapping call remained.","solutions":["Guard with apache_beam.typehints.is_nullable(typehint) before calling get_concrete_type_from_nullable.","Use the hint as-is when it is already non-nullable — no unwrapping is needed.","Check whether the hint changed from Optional[T] to T upstream and remove the now-unneeded unwrap call.","For unions that may contain NoneType, normalize with Any/Union handling before calling this helper."],"exampleFix":"# before\ninner = get_concrete_type_from_nullable(hint)\n# after\ninner = get_concrete_type_from_nullable(hint) if is_nullable(hint) else hint","handlingStrategy":"type-guard","validationCode":"from apache_beam.typehints import is_nullable, get_concrete_type_from_nullable\ndef concrete(hint):\n    return get_concrete_type_from_nullable(hint) if is_nullable(hint) else hint","typeGuard":"def is_optional_hint(h):\n    return is_nullable(h)","tryCatchPattern":"try:\n    inner = get_concrete_type_from_nullable(hint)\nexcept TypeError as e:\n    if 'not of nullable type' in str(e):\n        inner = hint\n    else:\n        raise","preventionTips":["Always gate unwrapping with is_nullable","Handle both Optional[T] and bare T in helper code","Track hint changes upstream so unwrap calls stay valid"],"tags":["python","apache-beam","typehints","nullable"],"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"}