MuntashirAkon/AppManager · error

Detect premature EOF

Error message

Detect premature EOF

What it means

IoUtils.readFully() reads an InputStream fully into a byte array, growing it as needed. When the caller demands the entire stream (readAll true and a known finite length) but the stream ends before delivering that many bytes, it throws EOFException("Detect premature EOF") rather than silently returning a short buffer. This protects against truncated or corrupted sources.

Source

Thrown at libcore/io/src/main/java/io/github/muntashirakon/io/IoUtils.java:55

    public static byte[] readFully(@NonNull InputStream is, int length, boolean readAll)
            throws IOException {
        byte[] output = {};
        if (length == -1) length = Integer.MAX_VALUE;
        int pos = 0;
        while (pos < length) {
            int bytesToRead;
            if (pos >= output.length) {
                bytesToRead = Math.min(length - pos, output.length + 1024);
                if (output.length < pos + bytesToRead) {
                    output = Arrays.copyOf(output, pos + bytesToRead);
                }
            } else {
                bytesToRead = output.length - pos;
            }
            int cc = is.read(output, pos, bytesToRead);
            if (cc < 0) {
                if (readAll && length != Integer.MAX_VALUE) {
                    throw new EOFException("Detect premature EOF");
                } else {
                    if (output.length != pos) {
                        output = Arrays.copyOf(output, pos);
                    }
                    break;
                }
            }
            pos += cc;
        }
        return output;
    }

    @AnyThread
    @NonNull
    public static String getInputStreamContent(@NonNull InputStream inputStream) throws IOException {
        return new String(IoUtils.readFully(inputStream, -1, true), Charset.defaultCharset());
    }

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Verify the source file/stream is complete (compare sizes/checksums) before readFully
  2. Retry the read or re-fetch the content if the source may be transiently truncated
  3. If a short read is acceptable, use a read variant/API that doesn't set readAll (or catch EOFException and use whatever bytes were read)

Example fix

// before
byte[] data = IoUtils.readFully(in, true); // EOFException on truncation
// after
try {
    data = IoUtils.readFully(in, true);
} catch (EOFException e) {
    data = /* fallback: re-fetch or accept partial */ refetchOrPartial();
}
Defensive patterns

Strategy: try-catch

Validate before calling

long expected = source.length(); long actual = countAvailable(source); if (actual < expected) throw new IOException("source truncated before read");

Try / catch

try { data = IoUtils.readFully(in, true); } catch (EOFException e) { /* re-fetch, retry, or accept partial bytes */ }

Prevention

When it happens

Trigger: Reading a stream whose declared/expected length is larger than the actual bytes available: truncated files, interrupted transfers, a remote file shrinking mid-read, or a content-length mismatch on streamed reads where readAll is set.

Common situations: Partially downloaded files; files modified/truncated by another process during read; network-backed streams cut short; reading through remote file providers whose source changed.

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 MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/eb438acb7212e6c0. Report an issue: GitHub.