apache/beam · error · TypeError

No types found for field

Error message

No types found for field %s

What it means

Raised while inferring the schema row type of a field when no usable non-None type could be computed from the union of candidate field types. Beam builds a RowTypeConstraint from schema fields; if the field's combined type hints collapse to nothing usable (e.g. all types are None), it cannot produce a final type and throws TypeError. This indicates the annotated schema types for the field are invalid or empty.

Solutions

  1. Add an explicit, non-None type annotation to the offending field (e.g. field: str).
  2. If the field is truly optional, annotate as Optional[T] with a concrete T so inference yields typehints.Optional[T].
  3. Remove NoneType-only entries from Unions on schema fields; keep at least one concrete type.
  4. Pass an explicit schema/row type via with_output_types or a user_type instead of relying on inference.

Example fix

// before
class Event:
    def __init__(self, id):
        self.id = None  # no type info
// after
class Event:
    def __init__(self, id: str):
        self.id = id
Defensive patterns

Strategy: type-guard

Validate before calling

import typing
for name, hint in typing.get_type_hints(MyClass).items():
    assert hint is not None and hint is not type(None), f'field {name} lacks a concrete type'
assert len(typing.get_args(hint)) > 0 or hint is not type(None)

Type guard

def has_concrete_hint(hint) -> bool:
    import typing
    return hint is not None and hint is not type(None) and (
        not typing.get_origin(hint) == typing.Union or
        any(a is not type(None) for a in typing.get_args(hint)))

Try / catch

try:
    row_type = beam.RowTypeConstraint.from_user_type(MyClass)
except TypeError as e:
    if 'No types found for field' in str(e):
        add_explicit_schema(MyClass)
    else:
        raise

Prevention

When it happens

Trigger: Calling schema inference (e.g. via core.py's schema type inference at core.py:4249) on a class/field where the merged field_types contain no non-None types and no single-type case applies — e.g. a field annotated only with None or with types that all reduce to NoneType.

Common situations: Using @beam.Row or dataclass schema inference with a field whose type hint is missing/None; passing Optional-only annotations in unsupported combinations; version changes in Beam's type inference handling of Optional/Union fields.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/transforms/core.py:4249

      row_dict = row.as_dict()
      for field in first_fields:
        field_types_by_field[field].add(
            trivial_inference.instance_to_type(row_dict.get(field)))

    # Determine the appropriate type for each field
    final_fields = []
    for field in first_fields:
      field_types = field_types_by_field[field]
      non_none_types = {t for t in field_types if t is not type(None)}

      if len(non_none_types) > 1:
        final_type = typehints.Union[tuple(non_none_types)]
      elif len(non_none_types) == 1 and len(field_types) == 1:
        final_type = non_none_types.pop()
      elif len(non_none_types) == 1 and len(field_types) == 2:
        final_type = typehints.Optional[non_none_types.pop()]
      else:
        raise TypeError("No types found for field %s", field)

      final_fields.append((field, final_type))

    return row_type.RowTypeConstraint.from_fields(final_fields)

  def get_output_type(self):
    return (
        self.get_type_hints().simple_output_type(self.label) or
        self.infer_output_type(None))

  def expand(self, pbegin):
    assert isinstance(pbegin, pvalue.PBegin)
    serialized_values = [self._coder.encode(v) for v in self.values]
    reshuffle = self.reshuffle

    # Avoid the "redistributing" reshuffle for 0 and 1 element Creates.
    # These special cases are often used in building up more complex
    # transforms (e.g. Write).

View on GitHub (pinned to 12126d8942)