iBotPeaches/Apktool · error · IOException
Stream advanced past chunk end.
Error message
Stream advanced past chunk end.
What it means
Thrown by ResChunkPullParser.skipChunk() when the underlying stream position is already beyond the current chunk's declared end (chunkOffset + header.size). The parser tracks chunk boundaries from each chunk header's size field; if the caller has read past that boundary (or the size field itself is corrupt/too small), skipping is impossible. Note that this IOException is thrown inside the method's own try block, so in practice it surfaces wrapped as "Error while skipping chunk." (error 42) with this message as the cause.
Source
Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResChunkPullParser.java:161
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) {
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;View on GitHub (pinned to 79b63384d7)
Solutions
- If you control the reading loop, never read from parser.stream() past a chunk's data: consume exactly dataSize() bytes before calling next().
- Verify the chunk's declared size: chunkSize() must be >= headerSize() and chunkStart() + chunkSize() must not exceed the file size; treat violations as a corrupt file.
- Regenerate or re-obtain the APK (re-download, unzip fully); corruption often comes from interrupted transfers.
- If parsing untrusted APKs, catch IOException around the next()/skipChunk() loop and report the resource file as undecodable instead of crashing.
Example fix
// before
while (parser.next()) {
// read body manually with extra bytes ...
in.readBytes(1024); // reads past chunk end
}
// after
while (parser.next()) {
long remaining = parser.chunkEnd() - in.position();
// consume at most `remaining` bytes, then let next() skip the rest
} Defensive patterns
Strategy: validation
Validate before calling
// Before next()/skipChunk(), ensure we have not overrun the current chunk
if (parser.isChunk()) {
long position = parser.stream().position();
long chunkEnd = parser.chunkStart() + parser.chunkSize();
if (position > chunkEnd) {
throw new IOException("Bug: read past chunk end by " + (position - chunkEnd) + " bytes");
}
} Try / catch
try {
while (parser.next()) { /* ... */ }
} catch (IOException ex) {
if (ex.getMessage() != null && ex.getMessage().contains("chunk end")) {
// chunk-size metadata vs. reads mismatch -> treat file/loop as broken
}
throw ex;
} Prevention
- Never read from parser.stream() beyond dataSize()/chunkEnd() for the current chunk
- Consume chunk bodies exactly; let next() do the skipping
- Validate chunkSize() >= headerSize() and chunk boundaries against total file size before trusting them
When it happens
Trigger: Calling next() after manually reading more bytes from parser.stream() than the chunk contained; a chunk header in resources.arsc or a binary XML file declaring a size smaller than the data a nested parser consumed; obfuscated/packed APKs with hand-crafted chunk sizes; calling skipChunk() twice without an intervening next().
Common situations: Decoding obfuscated or resource-shrunk APKs whose arsc chunk size fields were rewritten incorrectly; custom code that interleaves direct BinaryDataInputStream reads with the pull parser; truncated then re-padded files where sizes no longer align.
Related errors
- Stream advanced past chunk header 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/8a3f56333c07d4f9.
Report an issue: GitHub.