iBotPeaches/Apktool · critical · IOException

Error while reading chunk header.

Error message

Error while reading chunk header.

What it means

ResChunkPullParser wraps any non-EOF IOException raised while reading an 8-byte chunk header (malformed length fields causing overreads, stream failures, closed streams) in this generic message, chaining the original exception. It is the transport-level failure counterpart of the structural check at [38].

Source

Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResChunkPullParser.java:146

        try {
            mChunkOffset = mIn.position();
            ResChunkHeader chunkHeader = ResChunkHeader.read(mIn);

            if (chunkHeader.headerSize < ResChunkHeader.SIZE
                    || chunkHeader.size < chunkHeader.headerSize) {
                throw new IOException(
                    String.format("Invalid chunk header: type=0x%04x, headerSize=%s, size=%s",
                        chunkHeader.type, chunkHeader.headerSize, chunkHeader.size));
            }

            mChunkHeader = chunkHeader;
            return true;
        } catch (EOFException ignored) {
            // End of chunks due to end of stream.
            mChunkOffset = OFFSET_ENDED;
            return false;
        } catch (IOException ex) {
            throw new IOException("Error while reading chunk header.", ex);
        }
    }

    public int skipChunk() throws IOException {
        if (mChunkHeader == null) {
            throw new IllegalStateException();
        }
        try {
            long position = mIn.position();
            long chunkEnd = chunkEnd();
            if (position == chunkEnd) {
                return 0;
            }
            if (position > chunkEnd) {
                throw new IOException("Stream advanced past chunk end.");
            }
            return mIn.skipBytes((int) (chunkEnd - position));
        } catch (EOFException ignored) {

View on GitHub (pinned to 79b63384d7)

Solutions

  1. Inspect the chained cause for the exact I/O failure class.
  2. Prefer parsing from a fully materialized byte array (ByteArrayInputStream) so transport errors are impossible during parse.
  3. Verify the input is a complete, checksummed copy before parsing.
  4. If the cause is overreading past a size limit, the file is malformed — treat as corruption per [38].

Example fix

// before
parser.parse(socket.getInputStream()); // stream may drop mid-parse

// after
byte[] data = socket.getInputStream().readAllBytes(); // complete first
parser.parse(new ByteArrayInputStream(data));
Defensive patterns

Strategy: fallback

Validate before calling

// materialize input fully so transport I/O cannot fail mid-parse
byte[] data = inputStream.readAllBytes();
parser.parse(new ByteArrayInputStream(data));

Try / catch

try {
    parser.parse(new ByteArrayInputStream(data));
} catch (IOException e) {
    if ("Error while reading chunk header.".equals(e.getMessage())) {
        Throwable cause = e.getCause(); // overread => malformed; other => stream issue
    }
}

Prevention

When it happens

Trigger: The underlying BinaryDataInputStream throws while reading header fields — stream closed mid-parse, network/disk I/O error, or header values that force reads past the size limit set on the pull parser.

Common situations: Parsing from live network streams that drop; InputStream closed by another thread; truncated files where header reads cross EOF in a way not caught as plain EOFException; zip streams with inconsistent entry sizes.

Related errors


AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14). Data as JSON: /api/errors/f9d257160ddd9431. Report an issue: GitHub.