iBotPeaches/Apktool · error · IOException
Stream advanced past chunk header end.
Error message
Stream advanced past chunk header end.
What it means
Thrown by ResChunkPullParser.skipHeader() when the stream position is already past the chunk header's end (chunkOffset + header.headerSize). This means the caller consumed part or all of the header region before asking to skip it — the parser cannot skip backwards. Like error 40, this throw occurs inside the method's try block and is re-wrapped as 'Error while skipping chunk header.' (error 45) in practice.
Source
Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResChunkPullParser.java:182
} catch (EOFException ignored) {
throw new EOFException("Unexpected EOF while skipping chunk.");
} catch (IOException ex) {
throw new IOException("Error while skipping chunk.", ex);
}
}
public int skipHeader() throws IOException {
if (mChunkHeader == null) {
throw new IllegalStateException();
}
try {
long position = mIn.position();
long headerEnd = headerEnd();
if (position == headerEnd) {
return 0;
}
if (position > headerEnd) {
throw new IOException("Stream advanced past chunk header end.");
}
return mIn.skipBytes((int) (headerEnd - position));
} catch (EOFException ignored) {
throw new EOFException("Unexpected EOF while skipping chunk header.");
} catch (IOException ex) {
throw new IOException("Error while skipping chunk header.", ex);
}
}
}
View on GitHub (pinned to 79b63384d7)
Solutions
- Do not read header bytes from stream() yourself; use the parser's accessors and call skipHeader() exactly once per chunk.
- Check in.position() < parser.headerEnd() before calling skipHeader().
- Validate headerSize >= ResChunkHeader.SIZE (8) — next() already rejects headers smaller than that, so a smaller value indicates tampering.
Example fix
// before int type = in.readShort(); // consumed part of the header parser.skipHeader(); // throws: position > headerEnd // after int type = parser.chunkType(); // accessor, no stream consumption parser.skipHeader();
Defensive patterns
Strategy: validation
Validate before calling
// Only skip a header we have not started reading
if (parser.isChunk() && parser.stream().position() < parser.chunkStart() + parser.headerSize()) {
parser.skipHeader();
} else {
throw new IllegalStateException("Header already (partially) consumed");
} Try / catch
try {
parser.skipHeader();
} catch (IOException ex) {
// header overrun or I/O failure; check cause chain and abort chunk parsing
} Prevention
- Use accessors chunkType()/headerSize()/chunkSize() instead of raw stream reads of the header
- Call skipHeader() at most once per chunk, before any body reads
- Validate headerSize >= 8 (ResChunkHeader.SIZE) when parsing untrusted files
When it happens
Trigger: Reading header fields manually from parser.stream() and then calling skipHeader(); calling skipHeader() twice for the same chunk; a chunk header whose headerSize field is inconsistent with what was actually read.
Common situations: Custom parsers that inspect the raw header bytes (type, headerSize, size) directly instead of using the accessors (chunkType(), headerSize(), chunkSize()); obfuscated APKs with malformed headerSize values.
Related errors
- Stream advanced past chunk end.
- Repeated type spec: pkgId=0x%02x, typeId=0x%02x, typeName=%s
- Repeated entry spec: pkgId=0x%02x, typeId=0x%02x, entryId=0x
- Repeated entry: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x,
- Unexpected EOF while skipping chunk.
AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14).
Data as JSON: /api/errors/b8199e2003a7a289.
Report an issue: GitHub.