{"record":{"id":"70484f6504e67378","repo":"apache/beam","slug":"could-not-encode-message-as-bytes","errorCode":null,"errorMessage":"Could not encode message as bytes","messagePattern":"Could not encode message as bytes","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/RowMessages.java","lineNumber":122,"sourceCode":"    private RowToBytesFn(\n        Schema schema,\n        SerializableFunction<Row, T> fromRowFn,\n        ProcessFunction<? super T, byte[]> toBytesFn) {\n      this.schema = schema;\n      this.fromRowFn = fromRowFn;\n      this.toBytesFn = toBytesFn;\n    }\n\n    @Override\n    public byte[] apply(Row row) {\n      if (!schema.equivalent(row.getSchema())) {\n        row = switchFieldsOrder(row);\n      }\n      final T message = fromRowFn.apply(row);\n      try {\n        return toBytesFn.apply(message);\n      } catch (Exception e) {\n        throw new IllegalStateException(\"Could not encode message as bytes\", e);\n      }\n    }\n\n    private Row switchFieldsOrder(Row row) {\n      Row.Builder convertedRow = Row.withSchema(schema);\n      schema.getFields().forEach(field -> convertedRow.addValue(row.getValue(field.getName())));\n      return convertedRow.build();\n    }\n  }\n}\n","sourceCodeStart":104,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/RowMessages.java#L104-L133","documentation":"RowMessages.rowToBytesFn converts a Row to a protobuf message via fromRowFn and then serializes it. If the toBytes step throws (serialization failure), it is rethrown as IllegalStateException 'Could not encode message as bytes'.","triggerScenarios":"Applying rowToBytesFn where the Row does not match the proto schema (wrong types/field names) so message construction succeeds partially but toBytesFn fails, or the supplied toBytes function itself fails.","commonSituations":"Row schema drift after proto regeneration (field renamed/retyped), null values in non-nullable proto fields, writing rows built against an outdated Schema to a proto-based sink.","solutions":["Confirm the Row schema matches the current proto descriptor (field names, types, nullability).","Regenerate/rebuild rows from the updated proto-generated class so fromRowFn/toBytesFn agree.","Catch and log the IllegalStateException with the underlying cause to identify the failing field during serialization."],"exampleFix":"// before\nbytes = row.apply(RowMessages.rowToBytesFn(Msg.getDescriptor(), Msg.class));\n\n// after\nif (!row.getSchema().equivTo(SchemaOptions... )) { /* validate row schema matches proto */ }\nbytes = row.apply(\"RowsToProto\", RowMessages.rowToBytesFn(Msg.getDescriptor(), Msg.class));","handlingStrategy":"try-catch","validationCode":"// Java: confirm row schema matches proto before serializing\nif (!row.getSchema().getFieldNames().equals(expectedProtoFieldNames)) {\n  throw new IllegalArgumentException(\"Row schema mismatch with proto descriptor\");\n}","typeGuard":null,"tryCatchPattern":"// Java\ntry {\n  byte[] out = rowToBytesFn.apply(row);\n} catch (IllegalStateException e) {\n  // log e.getCause(); send row to a dead-letter output\n}","preventionTips":["Regenerate rows whenever the proto descriptor changes.","Avoid null values in proto fields that are not nullable."],"tags":["java","protobuf","serialization","schema"],"backgroundTag":"json-marshal-failed","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"}