{"record":{"id":"2e1fc875c08539be","repo":"apache/beam","slug":"cannot-cast-s-to-a-compatible-object-to-build-bytestring","errorCode":null,"errorMessage":"Cannot cast %s to a compatible object to build ByteString.","messagePattern":"Cannot cast (.+?) to a compatible object to build ByteString\\.","errorType":"exception","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BeamRowToStorageApiProto.java","lineNumber":120,"sourceCode":"          .put(TypeName.FLOAT, o -> Double.valueOf(o.toString()))\n          .put(TypeName.DOUBLE, Function.identity())\n          .put(TypeName.STRING, Function.identity())\n          .put(TypeName.BOOLEAN, Function.identity())\n          // A Beam DATETIME is actually a timestamp, not a DateTime.\n          .put(TypeName.DATETIME, o -> ((ReadableInstant) o).getMillis() * 1000)\n          .put(TypeName.BYTES, BeamRowToStorageApiProto::toProtoByteString)\n          .put(TypeName.DECIMAL, o -> serializeBigDecimalToNumeric((BigDecimal) o))\n          .build();\n\n  private static ByteString toProtoByteString(Object o) {\n    if (o instanceof byte[]) {\n      return ByteString.copyFrom((byte[]) o);\n    } else if (o instanceof ByteBuffer) {\n      return ByteString.copyFrom((ByteBuffer) o);\n    } else if (o instanceof String) {\n      return ByteString.copyFromUtf8((String) o);\n    } else {\n      throw new ClassCastException(\n          String.format(\n              \"Cannot cast %s to a compatible object to build ByteString.\", o.getClass()));\n    }\n  }\n\n  // A map of supported logical types to their encoding functions.\n  static final Map<String, BiFunction<LogicalType<?, ?>, Object, Object>> LOGICAL_TYPE_ENCODERS =\n      ImmutableMap.<String, BiFunction<LogicalType<?, ?>, Object, Object>>builder()\n          .put(\n              SqlTypes.DATE.getIdentifier(),\n              (logicalType, value) -> (int) ((LocalDate) value).toEpochDay())\n          .put(\n              SqlTypes.TIME.getIdentifier(),\n              (logicalType, value) -> CivilTimeEncoder.encodePacked64TimeMicros((LocalTime) value))\n          .put(\n              SqlTypes.DATETIME.getIdentifier(),\n              (logicalType, value) ->\n                  CivilTimeEncoder.encodePacked64DatetimeMicros((LocalDateTime) value))","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BeamRowToStorageApiProto.java#L102-L138","documentation":"BeamRowToStorageApiProto.toProtoByteString converts a Beam Row field value (BYTES-typed column) into a protobuf ByteString. It accepts byte[], ByteBuffer, and String; any other runtime type triggers ClassCastException. This means the Row's declared BYTES field actually holds an incompatible object.","triggerScenarios":"Building a Beam Row where a BYTES field is set with a non-byte value (e.g. an int, a List<Byte>, or a custom object) and then writing to BigQuery via Storage API","commonSituations":"Rows constructed manually with row.getBytes(i) mismatches, values deserialized from another format retaining exotic types, or schema changes where a column switched from STRING to BYTES but values weren't converted.","solutions":["Convert the value to byte[] before inserting into the Row: value.toString().getBytes(UTF_8) or ((ByteBuffer) v).array()","Verify the field's declared Beam FieldType matches the value actually stored in the Row","Use Schema.FieldType.BYTES consistently from the source that populates the row","Log o.getClass() at the failing site to identify the actual runtime type"],"exampleFix":"// before\nrow = Row.withSchema(schema).addValues(someString).build(); // BYTES column\n// after\nrow = Row.withSchema(schema).addValues(someString.getBytes(StandardCharsets.UTF_8)).build();","handlingStrategy":"type-guard","validationCode":"// Java\nif (!(v instanceof byte[] || v instanceof ByteBuffer || v instanceof String)) {\n  throw new IllegalStateException(\"BYTES column value must be byte[]/ByteBuffer/String, got \" + v.getClass());\n}","typeGuard":"// Java\nstatic ByteString toByteStringSafe(Object o) {\n  if (o instanceof byte[]) return ByteString.copyFrom((byte[]) o);\n  if (o instanceof ByteBuffer) return ByteString.copyFrom((ByteBuffer) o);\n  if (o instanceof String) return ByteString.copyFromUtf8((String) o);\n  return null; // caller checks\n}","tryCatchPattern":"// Java\ntry {\n  proto = BeamRowToStorageApiProto.messageFromBeamRow(...);\n} catch (ClassCastException e) {\n  if (e.getMessage().contains(\"compatible object to build ByteString\")) {\n    // coerce the offending field to byte[] before writing\n  }\n  throw e;\n}","preventionTips":["Populate BYTES fields only with byte[] (or ByteBuffer/String)","Assert row value types match the declared Schema in tests","Convert strings to UTF-8 bytes explicitly at the row-construction site"],"tags":["java","bigquery","beam-schema","classcast"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}