iBotPeaches/Apktool · critical · IOException
Invalid chunk header: type=0x%04x, headerSize=%s, size=%s
Error message
Invalid chunk header: type=0x%04x, headerSize=%s, size=%s
What it means
ResChunkPullParser validates every chunk header: headerSize must be >= ResChunkHeader.SIZE (8) and the chunk's total size must be >= its header size. Violations mean the file's chunk framing is broken — the stream position can no longer be trusted — so an IOException with the offending type/headerSize/size values is thrown.
Source
Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResChunkPullParser.java:134
if (mChunkHeader != null) {
skipChunk();
mChunkHeader = null;
}
if (mIn.position() >= mOffset + mSize) {
// End of chunks due to size limit.
mChunkOffset = OFFSET_ENDED;
return false;
}
// Read the chunk header at the current position.
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();View on GitHub (pinned to 79b63384d7)
Solutions
- Use the three reported values (type, headerSize, size) to locate the bad chunk in a hex dump — headerSize must be >= 8 and size >= headerSize.
- Re-obtain the file/APK from a trusted source and compare checksums.
- Validate with aapt2/apkanalyzer; if they also fail, the file itself is broken.
- For packer-mangled files, find an unprotected build — header repair is rarely worth it.
Defensive patterns
Strategy: validation
Validate before calling
ByteBuffer buf = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
while (buf.remaining() >= 8) {
int type = buf.getShort() & 0xFFFF;
int headerSize = buf.getShort() & 0xFFFF;
int size = buf.getInt();
if (headerSize < 8 || size < headerSize || size > buf.remaining()) {
throw new IOException(String.format("Bad chunk 0x%04x at 0x%x", type, buf.position() - 8));
}
buf.position(buf.position() + size - 8);
} Try / catch
try {
parser.parse(in);
} catch (IOException e) {
if (e.getMessage().contains("Invalid chunk header")) {
// structural corruption — reject file, re-obtain artifact
}
} Prevention
- Checksum files after transfer before parsing.
- Pre-validate chunk framing when accepting files from untrusted sources.
- Treat header anomalies as corruption, never skip-and-continue.
When it happens
Trigger: Parsing (arsc or AXML) a file whose chunk headers were corrupted or crafted with impossible sizes — truncation at a chunk boundary, byte-level corruption, deliberate fuzzing, or a packer that rewrote headers incorrectly.
Common situations: Corrupt resource files from interrupted transfers; obfuscated arsc/AXML from protectors; fuzzing corpora; files patched in a hex editor with wrong length fields.
Related errors
- Input file is empty.
- Unexpected chunk:
- Config size < 8
- Input file is empty.
- Error while reading chunk header.
AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14).
Data as JSON: /api/errors/91fcbf4d3ed78531.
Report an issue: GitHub.