apache/beam · error · CoderException

EOF encountered decoding a ValueKind

Error message

EOF encountered decoding a ValueKind

What it means

ValueKindCoder.decode reads a single byte; -1 means the stream has ended with no ValueKind to read. The coder wraps the EOFException in a CoderException so callers can distinguish premature stream end from corrupt data. This indicates truncation or decoding past the last element.

Solutions

  1. Verify writer and reader element counts match (one ValueKind byte per element).
  2. Check transport integrity — compare expected byte counts to detect truncation.
  3. Fix off-by-one loops that call decode more times than encode.
  4. Catch CoderException with an EOFException cause and treat it as end-of-stream or a truncation error.

Example fix

// before
ValueKind k = kindCoder.decode(in);
// after
try {
  ValueKind k = kindCoder.decode(in);
} catch (CoderException e) {
  if (e.getCause() instanceof EOFException) {
    return; // clean end of stream, or flag truncation
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the stream still has at least one byte before decoding
in.mark(1);
boolean empty = in.read() == -1;
in.reset();
if (empty) throw new EOFException("No ValueKind byte available");

Type guard

static boolean hasMoreBytes(InputStream in) throws IOException {
  return in.available() > 0;
}

Try / catch

try {
  ValueKind k = kindCoder.decode(in);
} catch (CoderException e) {
  if (e.getCause() instanceof EOFException) {
    return; // clean end of stream, or flag truncation
  }
  throw e;
}

Prevention

When it happens

Trigger: Reading an empty stream with decode; a stream written with fewer ValueKind bytes than decode attempts; off-by-one in element counts consuming one byte too many; truncated network/file transport of runner metadata.

Common situations: Truncated gRPC/Dataflow harness payloads; custom runner serialization with mismatched buffer counts; replaying partial log/state files cut off mid-record.

Related errors


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

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/coders/ValueKindCoder.java:59

  private static final ValueKindCoder INSTANCE = new ValueKindCoder();
  private static final TypeDescriptor<ValueKind> TYPE_DESCRIPTOR =
      TypeDescriptor.of(ValueKind.class);

  private ValueKindCoder() {}

  @Override
  public void encode(ValueKind value, OutputStream outStream) throws IOException, CoderException {
    if (value == null) {
      throw new CoderException("cannot encode a null ValueKind");
    }
    outStream.write(ValueKindUtil.toProto(value).getNumber());
  }

  @Override
  public ValueKind decode(InputStream inStream) throws IOException, CoderException {
    int number = inStream.read();
    if (number == -1) {
      throw new CoderException(new EOFException("EOF encountered decoding a ValueKind"));
    }
    Elements.ValueKind.@Nullable Enum proto = Elements.ValueKind.Enum.forNumber(number);
    if (proto == null) {
      throw new CoderException("Unknown ValueKind number: " + number);
    }

    return ValueKindUtil.fromProto(proto);
  }

  @Override
  public boolean consistentWithEquals() {
    return true;
  }

  @Override
  public boolean isRegisterByteSizeObserverCheap(ValueKind value) {
    return true;
  }

View on GitHub (pinned to 12126d8942)