apache/iceberg · warning · IOException

Failed to read bytes: bytes in stream

Error message

Failed to read %d bytes: %d bytes in stream

What it means

During ContentCache.download, the cached read got fewer bytes than the file's declared length before reaching EOF. The cache is abandoned by throwing IOException so the caller falls back to a non-caching input stream; the message reports how many bytes were actually read.

Solutions

  1. Retry the read; the fallback non-caching path usually succeeds.
  2. Verify the object's current size matches the length in table metadata.
  3. Check for writers overwriting files in place; Iceberg files must be immutable.
  4. Investigate storage client/proxy truncation (timeouts, range request handling).

Example fix

// before
ContentCache cache = new ContentCache(0, 64 * 1024 * 1024); // cache huge files, hit truncation
// after
ContentCache cache = new ContentCache(0, 8 * 1024 * 1024); // cache small files only
Defensive patterns

Strategy: retry

Validate before calling

long actualLength = delegate.getLength();
if (declaredLength != actualLength) { refreshMetadata(); }

Try / catch

try {
  return cachedInputFile.newStream();
} catch (IOException | UncheckedIOException e) {
  return delegate.newStream(); // non-caching fallback is built in
}

Prevention

When it happens

Trigger: The input stream returned by the delegate ends prematurely: file truncated or rewritten to a smaller size after length was read, or the storage client returned a short/incomplete response body.

Common situations: Concurrent overwrite of an object in stores without atomic replace; corrupted/incomplete multipart upload; proxy or CDN truncating responses; stale length from stale metadata.

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/c949f747d40935a5. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/io/ContentCache.java:257

  }

  private static FileContent download(InputFile input) {
    try (SeekableInputStream stream = input.newStream()) {
      long fileLength = input.getLength();
      long totalBytesToRead = fileLength;
      List<ByteBuffer> buffers = Lists.newArrayList();

      while (totalBytesToRead > 0) {
        // read the stream in chunks
        int bytesToRead = (int) Math.min(BUFFER_CHUNK_SIZE, totalBytesToRead);
        byte[] buf = new byte[bytesToRead];
        int bytesRead = IOUtil.readRemaining(stream, buf, 0, bytesToRead);
        totalBytesToRead -= bytesRead;

        if (bytesRead < bytesToRead) {
          // Read less than it should be, possibly hitting EOF. Abandon caching by throwing
          // IOException and let the caller fallback to non-caching input file.
          throw new IOException(
              String.format(
                  Locale.ROOT,
                  "Failed to read %d bytes: %d bytes in stream",
                  fileLength,
                  fileLength - totalBytesToRead));
        } else {
          buffers.add(ByteBuffer.wrap(buf));
        }
      }

      return new FileContent(fileLength, buffers);
    } catch (IOException ex) {
      throw new UncheckedIOException(ex);
    }
  }
}

View on GitHub (pinned to 86d9c8fc54)