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

  1. Inspect the cause IOException for the root I/O failure.
  2. Verify the InputStream is open and reachable at decode time.
  3. Retry the read if the source is transiently unavailable (network FS, object store).
  4. 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

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/8919950900d0ccc2. Report an issue: GitHub.