{"record":{"id":"02a4f7d69b44d904","repo":"apache/beam","slug":"unable-to-deterministically-encode-non-frozen-s-of-type-s","errorCode":null,"errorMessage":"Unable to deterministically encode non-frozen '%s' of type '%s' for the input of '%s'","messagePattern":"Unable to deterministically encode non-frozen '(.+?)' of type '(.+?)' for the input of '(.+?)'","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/coders/coder_impl.py","lineNumber":499,"sourceCode":"      self.encode_special_deterministic(value, stream)\n    else:\n      stream.write_byte(UNKNOWN_TYPE)\n      self.fallback_coder_impl.encode_to_stream(value, stream, nested)\n\n  def encode_special_deterministic(self, value, stream):\n    if self.warn_deterministic_fallback:\n      _LOGGER.warning(\n          \"Using fallback deterministic coder for type '%s' in '%s'. \",\n          type(value),\n          self.requires_deterministic_step_label)\n      self.warn_deterministic_fallback = False\n    if isinstance(value, proto_utils.message_types):\n      stream.write_byte(PROTO_TYPE)\n      self.encode_type(type(value), stream)\n      stream.write(value.SerializePartialToString(deterministic=True), True)\n    elif dataclasses.is_dataclass(value):\n      if not type(value).__dataclass_params__.frozen:\n        raise TypeError(\n            \"Unable to deterministically encode non-frozen '%s' of type '%s' \"\n            \"for the input of '%s'\" %\n            (value, type(value), self.requires_deterministic_step_label))\n      init_fields = [field for field in dataclasses.fields(value) if field.init]\n      try:\n        if any(field.kw_only for field in init_fields):\n          stream.write_byte(DATACLASS_KW_ONLY_TYPE)\n          self.encode_type(type(value), stream)\n          stream.write_var_int64(len(init_fields))\n          for field in init_fields:\n            stream.write(field.name.encode(\"utf-8\"), True)\n            self.encode_to_stream(getattr(value, field.name), stream, True)\n        else:  # Not using kw_only, we can pass parameters by position.\n          stream.write_byte(DATACLASS_TYPE)\n          self.encode_type(type(value), stream)\n          values = [getattr(value, field.name) for field in init_fields]\n          self.iterable_coder_impl.encode_to_stream(values, stream, True)\n      except Exception as e:","sourceCodeStart":481,"sourceCodeEnd":517,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/coders/coder_impl.py#L481-L517","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Declare the dataclass frozen: @dataclasses.dataclass(frozen=True).","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.","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).","Convert the value to a NamedTuple or frozen dataclass before passing it into the PTransform."],"exampleFix":"# before\n@dataclasses.dataclass\nclass Key:\n    id: int\n    tag: str\n\n# after\n@dataclasses.dataclass(frozen=True)\nclass Key:\n    id: int\n    tag: str","handlingStrategy":"validation","validationCode":"import dataclasses\ndef ensure_frozen_dataclass(value):\n    if dataclasses.is_dataclass(value) and not type(value).__dataclass_params__.frozen:\n        raise TypeError(f\"{type(value).__name__} must be frozen for deterministic coding\")\n    return value","typeGuard":"def is_frozen_dataclass(value) -> bool:\n    import dataclasses\n    return dataclasses.is_dataclass(value) and type(value).__dataclass_params__.frozen","tryCatchPattern":"try:\n    coder.encode(value)\nexcept TypeError as e:\n    logger.error(\"Non-deterministic value: %s\", e)\n    value = to_frozen_form(value)","preventionTips":["Always declare pipeline key types as frozen dataclasses or NamedTuples","Lint for @dataclass without frozen=True in pipeline data models","Prefer immutable value objects for anything crossing a GroupByKey"],"tags":["apache-beam","python","coder","serialization","dataclass"],"backgroundTag":"unsupported-operation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}