apache/beam · warning
Failure parsing TableRow
Error message
Failure parsing TableRow
What it means
While emitting successful rows after a Storage Write API append, Beam converts each serialized proto row back into a TableRow (via protoToTableRow). If conversion of any individual row throws, that row is logged with this warning and skipped rather than failing the whole batch — other rows still produce output.
Solutions
- Inspect the chained exception to identify the malformed row and field causing conversion failure.
- Ensure the descriptor matches the schema used when rows were serialized (avoid mid-stream schema changes, or use schema-consistent destinations).
- Configure failed-row routing (withFailedRows/withErrorFn) so bad rows go to an error output instead of being dropped by this path.
- Upgrade Beam — protoToTableRow conversion bugs are fixed periodically.
Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm serialized rows decode with the current descriptor:
try { DynamicMessage.parseFrom(descriptor, rowBytes); } catch (Exception e) { /* route to dead-letter */ } Type guard
boolean rowParses(Descriptor d, ByteString bytes) { try { DynamicMessage.parseFrom(d, bytes); return true; } catch (Exception e) { return false; } } Try / catch
try { row = protoToTableRow(DynamicMessage.parseFrom(descriptor, rowBytes)); } catch (Exception e) { LOG.warn("Failure parsing TableRow", e); failedRowsReceiver.output(...); } Prevention
- Route failures with withFailedRows so malformed rows are captured, not dropped.
- Avoid schema changes mid-stream that invalidate serialized rows.
- Log row bytes and descriptor version when conversion fails to aid diagnosis.
When it happens
Trigger: flush() iterates over successfully appended serialized rows and calls protoToTableRow on DynamicMessage.parseFrom(descriptor, rowBytes); any exception (malformed row bytes, conversion bug, unexpected field values) triggers this per-row warning.
Common situations: Rows written by a different schema version than the descriptor used for parsing; corrupt or truncated serialized rows; custom proto-to-row conversion edge cases (e.g. unusual timestamp/numeric encodings).
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- Failure getting proto descriptor. Successful output will…
- BigQuery storage source must be split before being read
- Bounded Source is not BigQueryStorageStreamSource, unable…
- DynamicMessage is not supported.
- Failed to parse row filter text proto
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/da47b70d29d20385.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/StorageApiWriteUnshardedRecords.java:913
LOG.warn(
"Failure getting proto descriptor. Successful output will not be produced.",
e);
}
if (descriptor != null) {
for (int i = 0; i < c.protoRows.getSerializedRowsCount(); ++i) {
ByteString rowBytes = c.protoRows.getSerializedRowsList().get(i);
try {
TableRow row =
TableRowToStorageApiProto.tableRowFromMessage(
Preconditions.checkStateNotNull(appendClientInfo)
.getSchemaInformation(),
DynamicMessage.parseFrom(descriptor, rowBytes),
true,
successfulRowsPredicate);
org.joda.time.Instant timestamp = c.timestamps.get(i);
successfulRowsReceiver.outputWithTimestamp(row, timestamp);
} catch (Exception e) {
LOG.warn("Failure parsing TableRow", e);
}
}
}
}
},
appendRowsContext);
maybeTickleCache();
return inserts.getSerializedRowsCount();
}
String retrieveErrorDetails(Iterable<AppendRowsContext> failedContext) {
return StreamSupport.stream(failedContext.spliterator(), false)
.<@Nullable Throwable>map(AppendRowsContext::getError)
.filter(Objects::nonNull)
.map(
thrw ->
Preconditions.checkStateNotNull(thrw).toString()
+ "\n"View on GitHub (pinned to 12126d8942)