{"record":{"id":"797d1e2c76c388cb","repo":"apache/beam","slug":"tobytescoder-cannot-be-used-for-decoding","errorCode":null,"errorMessage":"ToBytesCoder cannot be used for decoding.","messagePattern":"ToBytesCoder cannot be used for decoding\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/coders/coders.py","lineNumber":435,"sourceCode":"\n  def is_deterministic(self):\n    # type: () -> bool\n    return True\n\n  def to_type_hint(self):\n    return str\n\n\nCoder.register_structured_urn(common_urns.coders.STRING_UTF8.urn, StrUtf8Coder)\n\n\nclass ToBytesCoder(Coder):\n  \"\"\"A default string coder used if no sink coder is specified.\"\"\"\n  def encode(self, value):\n    return value if isinstance(value, bytes) else str(value).encode('utf-8')\n\n  def decode(self, _):\n    raise NotImplementedError('ToBytesCoder cannot be used for decoding.')\n\n  def is_deterministic(self):\n    # type: () -> bool\n    return True\n\n\n# alias to the old class name for a courtesy to users who reference it\nToStringCoder = ToBytesCoder\n\n\nclass FastCoder(Coder):\n  \"\"\"Coder subclass used when a (faster) CoderImpl is supplied directly.\n\n  The Coder class defines _create_impl in terms of encode() and decode();\n  this class inverts that by defining encode() and decode() in terms of\n  _create_impl().\n  \"\"\"\n  def encode(self, value):","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/coders/coders.py#L417-L453","documentation":"ToBytesCoder is a write-only convenience coder: its encode converts anything to bytes, but it intentionally does not implement decode and raises NotImplementedError('ToBytesCoder cannot be used for decoding.') whenever decoding is attempted. It exists as a default when no sink coder is specified and reading back is never expected.","triggerScenarios":"Calling ToBytesCoder().decode(bytes) directly; pipelines or checkpoint mechanisms that try to read back data written with ToBytesCoder (checkpoint marks, side-input materialization, bag page values).","commonSituations":"Using ToBytesCoder as a general-purpose string coder because the name suggests 'to bytes', then a transform needs to decode; writing to sinks with the default coder and later reading that data in another step/job.","solutions":["Replace ToBytesCoder with a decodable coder such as coders.StrBytesCoder (or coders.BytesCoder for raw bytes)","Keep ToBytesCoder only on write-only paths where values are never read back","Decode at write time instead: store str/bytes elements and use a coder that round-trips"],"exampleFix":"// before\npcoll = pcoll | beam.Map(lambda x: str(x)) with coder ToBytesCoder() ... later decoded\n// after\npcoll = pcoll | beam.Map(lambda x: str(x)) with coder coders.StrBytesCoder()","handlingStrategy":"try-catch","validationCode":"if isinstance(coder, ToBytesCoder) and need_decoding:\n    coder = coders.StrBytesCoder()","typeGuard":"def is_decodable_coder(coder):\n    return not isinstance(coder, ToBytesCoder) and coder.is_deterministic() is not None","tryCatchPattern":"try:\n    value = coder.decode(blob)\nexcept NotImplementedError:\n    value = blob.decode('utf-8')  # ToBytesCoder wrote str(x).encode('utf-8')","preventionTips":["Never use ToBytesCoder where data will be read back","Use StrBytesCoder/BytesCoder for string/bytes data","Check coder round-trip support when choosing sink coders"],"tags":["python","apache-beam","coders","decode","write-only"],"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"}