apache/beam · error · CoderException

cannot encode a null value

Error message

cannot encode a null value

What it means

TableRowInfoCoder.encode throws CoderException when the TableRowInfo being serialized is null. The coder encodes a TableRow plus its unique id, and Beam coders must reject nulls since the encoded form cannot represent them. It surfaces when a null TableRowInfo enters a shuffle in the BigQuery write path.

Solutions

  1. Ensure the upstream DoFn never emits null TableRowInfo elements (guard before output).
  2. Filter or dead-letter records that fail to map to a TableRow before the write.
  3. In direct coder usage, null-check before invoking encode.

Example fix

// before
c.output(new TableRowInfo<>(maybeNullRow, id));
// after
if (maybeNullRow == null) {
  throw new IllegalArgumentException("Cannot emit null TableRow for id " + id);
}
c.output(new TableRowInfo<>(maybeNullRow, id));
Defensive patterns

Strategy: validation

Validate before calling

if (rowInfo == null || rowInfo.tableRow == null) {
  throw new IllegalArgumentException("TableRowInfo and its TableRow must not be null");
}

Type guard

boolean isValidRowInfo(TableRowInfo<?> info) { return info != null && info.tableRow != null; }

Prevention

When it happens

Trigger: Encoding a null TableRowInfo via TableRowInfoCoder during BigQueryIO writes, usually because an upstream DoFn emitted a null element or a null-valued KV reached the coder.

Common situations: Custom DoFns producing null TableRows or null unique ids feeding the BigQuery sink; tests calling encode(null, out) directly.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/d5d6c963659f8cff. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/TableRowInfoCoder.java:51

  private TableRowInfoCoder(Coder<ElementT> elementCoder) {
    this.elementCoder = elementCoder;
  }

  public static <ElementT> TableRowInfoCoder<ElementT> of(Coder<ElementT> elementCoder) {
    return new TableRowInfoCoder<>(elementCoder);
  }

  @Override
  public void encode(TableRowInfo<ElementT> value, OutputStream outStream) throws IOException {
    encode(value, outStream, Context.NESTED);
  }

  @Override
  public void encode(TableRowInfo<ElementT> value, OutputStream outStream, Context context)
      throws IOException {
    if (value == null) {
      throw new CoderException("cannot encode a null value");
    }
    elementCoder.encode(value.tableRow, outStream);
    idCoder.encode(value.uniqueId, outStream, context);
  }

  @Override
  public TableRowInfo<ElementT> decode(InputStream inStream) throws IOException {
    return decode(inStream, Context.NESTED);
  }

  @Override
  public TableRowInfo<ElementT> decode(InputStream inStream, Context context) throws IOException {
    return new TableRowInfo<>(elementCoder.decode(inStream), idCoder.decode(inStream, context));
  }

  @Override
  public void verifyDeterministic() throws NonDeterministicException {
    throw new NonDeterministicException(this, "TableRows are not deterministic.");

View on GitHub (pinned to 12126d8942)