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.
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)
Solutions
- Verify writer and reader element counts match (one ValueKind byte per element).
- Check transport integrity — compare expected byte counts to detect truncation.
- Fix off-by-one loops that call decode more times than encode.
- 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
- Keep writer/reader element counts symmetric.
- Compare expected vs actual byte counts on transport to catch truncation.
- Avoid decode loops without an end-of-stream check.
- Handle empty streams explicitly before decoding.
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
- Invalid encoded string length: {}
- error when decoding a textual integer
- Unknown ValueKind number: {}
- Unable to decode constant members from payload for ParamWind
- EOF encountered decoding 1 byte from input stream
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/a0588aa64b2d8f80.
Report an issue: GitHub.