apache/beam · error · TypeError

Unable to deterministically encode non-frozen '%s' of type '

Error message

Unable to deterministically encode non-frozen '%s' of type '%s' for the input of '%s'

What it means

Beam's deterministic coder (FastPrimitivesCoder in deterministic mode) can only encode dataclasses whose bytes are byte-for-byte reproducible. A non-frozen dataclass has mutable fields, so two structurally equal instances could encode differently, breaking deterministic ordering (needed e.g. for GroupByKey staging consistency). The coder raises TypeError instead of silently producing nondeterministic output.

Source

Thrown at sdks/python/apache_beam/coders/coder_impl.py:499

      self.encode_special_deterministic(value, stream)
    else:
      stream.write_byte(UNKNOWN_TYPE)
      self.fallback_coder_impl.encode_to_stream(value, stream, nested)

  def encode_special_deterministic(self, value, stream):
    if self.warn_deterministic_fallback:
      _LOGGER.warning(
          "Using fallback deterministic coder for type '%s' in '%s'. ",
          type(value),
          self.requires_deterministic_step_label)
      self.warn_deterministic_fallback = False
    if isinstance(value, proto_utils.message_types):
      stream.write_byte(PROTO_TYPE)
      self.encode_type(type(value), stream)
      stream.write(value.SerializePartialToString(deterministic=True), True)
    elif dataclasses.is_dataclass(value):
      if not type(value).__dataclass_params__.frozen:
        raise TypeError(
            "Unable to deterministically encode non-frozen '%s' of type '%s' "
            "for the input of '%s'" %
            (value, type(value), self.requires_deterministic_step_label))
      init_fields = [field for field in dataclasses.fields(value) if field.init]
      try:
        if any(field.kw_only for field in init_fields):
          stream.write_byte(DATACLASS_KW_ONLY_TYPE)
          self.encode_type(type(value), stream)
          stream.write_var_int64(len(init_fields))
          for field in init_fields:
            stream.write(field.name.encode("utf-8"), True)
            self.encode_to_stream(getattr(value, field.name), stream, True)
        else:  # Not using kw_only, we can pass parameters by position.
          stream.write_byte(DATACLASS_TYPE)
          self.encode_type(type(value), stream)
          values = [getattr(value, field.name) for field in init_fields]
          self.iterable_coder_impl.encode_to_stream(values, stream, True)
      except Exception as e:

View on GitHub (pinned to 12126d8942)

Solutions

  1. Declare the dataclass frozen: @dataclasses.dataclass(frozen=True).
  2. If mutation is needed, use attrs-style or provide a deterministic __encode__/__getstate__ path the coder understands, or encode a derived frozen/tuple key instead.
  3. If determinism is not actually required, disable the deterministic check for the step (e.g. use a non-deterministic coder or remove requires_determinism on the transform input).
  4. Convert the value to a NamedTuple or frozen dataclass before passing it into the PTransform.

Example fix

# before
@dataclasses.dataclass
class Key:
    id: int
    tag: str

# after
@dataclasses.dataclass(frozen=True)
class Key:
    id: int
    tag: str
Defensive patterns

Strategy: validation

Validate before calling

import dataclasses
def ensure_frozen_dataclass(value):
    if dataclasses.is_dataclass(value) and not type(value).__dataclass_params__.frozen:
        raise TypeError(f"{type(value).__name__} must be frozen for deterministic coding")
    return value

Type guard

def is_frozen_dataclass(value) -> bool:
    import dataclasses
    return dataclasses.is_dataclass(value) and type(value).__dataclass_params__.frozen

Try / catch

try:
    coder.encode(value)
except TypeError as e:
    logger.error("Non-deterministic value: %s", e)
    value = to_frozen_form(value)

Prevention

When it happens

Trigger: Encoding a value through a coder with requires_deterministic_step_label set (e.g. input to GroupByKey with a check that encoding is deterministic) when the value is an instance of a non-frozen @dataclass. encode_special_deterministic hits the is_dataclass branch, sees type(value).__dataclass_params__.frozen is False, and raises.

Common situations: Decorating a dataclass with plain @dataclass.dataclass and passing instances as GroupByKey keys; forgetting @dataclasses.dataclass(frozen=True); Beam upgrade adding deterministic-encoding enforcement for dataclasses.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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