apache/beam · error · TypeError

Cannot create Union without a sequence of types.

Error message

Cannot create Union without a sequence of types.

What it means

UnionHint.__getitem__ raises TypeError('Cannot create Union without a sequence of types.') when the subscription is not an iterable/set — i.e. someone writes Union[int] instead of Union[int, str] or passes a non-sequence. Beam's Union requires a collection of two or more type parameters to combine.

Solutions

  1. Always pass at least two types: Union[int, str]. If only one type remains, drop the Union and use the type directly.
  2. If building dynamically, wrap single values as a one-element list only if Beam's version accepts it, or special-case: t if single else Union[tuple(ts)].
  3. Prefer typing.Union from the typing module if you need single-argument tolerance, ensuring Beam accepts it (it checks __module__ == 'typing').
  4. Audit hint-building code for cases where a list of types can shrink to length 1.

Example fix

# before
hint = Union[int]  # single type
# after
hint = int  # or Union[int, str] for multiple
Defensive patterns

Strategy: validation

Validate before calling

def build_union(ts):
    if not isinstance(ts, (list, tuple, set)) or len(ts) < 2:
        raise ValueError('Union needs 2+ types')
    return Union[tuple(ts)]

Type guard

def is_nonempty_seq(x):
    return isinstance(x, (list, tuple, set)) and len(x) >= 2

Try / catch

try:
    hint = Union[params]
except TypeError as e:
    if 'without a sequence of types' in str(e):
        hint = params[0] if len(params) == 1 else Union[tuple(params)]
    else:
        raise

Prevention

When it happens

Trigger: Writing Union[int] with a single bare type; passing a single non-iterable object (Union[SomeClass]) or a generator not recognized as Iterable in older contexts; dynamic code building Union from a single variable.

Common situations: Refactors that collapse a union to one member; code generators building hints programmatically that special-case single-type lists incorrectly; confusion between typing.Union (which allows one arg) and Beam's Union.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/typehints/typehints.py:582

      sub_bindings = [
          match_type_variables(t, concrete_type) for t in self.union_types
          if is_consistent_with(concrete_type, t)
      ]
      if sub_bindings:
        return {
            var: Union[(sub[var] for sub in sub_bindings)]
            for var in set.intersection(
                *[set(sub.keys()) for sub in sub_bindings])
        }
      else:
        return {}

    def bind_type_variables(self, bindings):
      return Union[(bind_type_variables(t, bindings) for t in self.union_types)]

  def __getitem__(self, type_params):
    if not isinstance(type_params, (abc.Iterable, set)):
      raise TypeError('Cannot create Union without a sequence of types.')

    # Flatten nested Union's and duplicated repeated type hints.
    params = set()
    dict_union = None
    for t in type_params:
      validate_composite_type_param(
          t, error_msg_prefix='All parameters to a Union hint')

      if isinstance(t, self.UnionConstraint):
        params |= set(t.union_types)
      elif isinstance(t, DictConstraint):
        if dict_union is None:
          dict_union = t
        else:
          dict_union.key_type = Union[dict_union.key_type, t.key_type]
          dict_union.value_type = Union[dict_union.value_type, t.value_type]
      else:
        params.add(t)

View on GitHub (pinned to 12126d8942)