apache/iceberg · error · IOException
Failed to read header and fingerprint bytes
Error message
Failed to read header and fingerprint bytes
What it means
When reading the header throws an IOException (I/O failure rather than a short stream), IcebergDecoder.decode wraps it in a new IOException with the message "Failed to read header and fingerprint bytes" and the original exception as cause. It indicates an underlying I/O problem while reading the stream's header.
Source
Thrown at core/src/main/java/org/apache/iceberg/data/avro/IcebergDecoder.java:135
Schema writeSchema = resolver.findByFingerprint(fp);
if (writeSchema != null) {
addSchema(writeSchema);
return decoders.get(fp);
}
}
throw new MissingSchemaException("Cannot resolve schema for fingerprint: " + fp);
}
@Override
public D decode(InputStream stream, D reuse) throws IOException {
byte[] header = HEADER_BUFFER.get();
try {
if (!readFully(stream, header)) {
throw new BadHeaderException("Not enough header bytes");
}
} catch (IOException e) {
throw new IOException("Failed to read header and fingerprint bytes", e);
}
if (IcebergEncoder.V1_HEADER[0] != header[0] || IcebergEncoder.V1_HEADER[1] != header[1]) {
throw new BadHeaderException(
String.format(
Locale.ROOT, "Unrecognized header bytes: 0x%02X 0x%02X", header[0], header[1]));
}
RawDecoder<D> decoder = getDecoder(FP_BUFFER.get().getLong(2));
try {
return decoder.decode(stream, reuse);
} catch (UncheckedIOException e) {
throw new AvroRuntimeException(e);
}
}
/**View on GitHub (pinned to 86d9c8fc54)
Solutions
- Inspect the cause IOException for the root I/O failure.
- Verify the InputStream is open and reachable at decode time.
- Retry the read if the source is transiently unavailable (network FS, object store).
- Ensure no other thread closes the shared stream concurrently.
Example fix
// before
decoder.decode(stream, null); // IOException: Failed to read header...
// after
try {
decoder.decode(stream, null);
} catch (IOException e) {
if (e.getCause() != null) log.warn("Root cause", e.getCause());
throw e;
} Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
try { return decoder.decode(stream, reuse); } catch (IOException e) { if (isTransient(e.getCause())) { return retryDecode(stream, reuse); } throw e; } Prevention
- Keep the InputStream open until decode completes
- Use durable local files instead of flaky network streams when possible
- Inspect the cause chain for the real I/O failure
When it happens
Trigger: decode(stream, reuse) where stream.read() throws mid-header: broken file handle, network stream reset, closed InputStream, or disk read error.
Common situations: Reading from a remote/encrypted FS where the connection drops; stream closed by another component; permissions/IO errors on read.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Failed to get stream length
- Failed to get stream length: no open stream
- Not enough header bytes
- Decoding datum failed
- Cannot read manifest list file: %s
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/8919950900d0ccc2.
Report an issue: GitHub.