MuntashirAkon/AppManager · error · IOException
Stream is not in the BZip2 format
Error message
Stream is not in the BZip2 format
What it means
init() reads the first three bytes and throws IOException("Stream is not in the BZip2 format") when they are not the magic 'BZh'. The library refuses to parse data that is not a BZip2 stream rather than returning garbage.
Solutions
- Verify the input is really bzip2 by checking the first three bytes are 'B','Z','h' before wrapping.
- Use CompressorStreamFactory with auto-detection (CompressorStreamFactory.detect) instead of hardcoding bzip2.
- Check the InputStream position — skip any leading container/protocol headers before decompressing.
- Confirm the file was actually compressed with bzip2 (e.g. `file data.bz2` shows 'bzip2 compressed data').
Example fix
// before
InputStream in = new BZip2CompressorInputStream(new FileInputStream(anyFile));
// after
PushbackInputStream pb = new PushbackInputStream(new FileInputStream(anyFile), 3);
byte[] magic = new byte[3];
if (pb.read(magic) != 3 || magic[0] != 'B' || magic[1] != 'Z' || magic[2] != 'h') {
pb.unread(magic);
throw new IllegalArgumentException("Not a bzip2 stream");
}
InputStream in = new BZip2CompressorInputStream(pb); Defensive patterns
Strategy: validation
Validate before calling
byte[] head = new byte[3];
if (in.read(head) != 3 || head[0] != 'B' || head[1] != 'Z' || head[2] != 'h') {
throw new IllegalArgumentException("not a bzip2 stream");
}
// then wrap (use PushbackInputStream to unread the 3 bytes) Type guard
static boolean looksLikeBzip2(byte[] head) {
return head != null && head.length >= 3 && head[0] == 'B' && head[1] == 'Z' && head[2] == 'h';
} Try / catch
try {
InputStream in = new BZip2CompressorInputStream(raw);
} catch (IOException e) {
// sniff real format via CompressorStreamFactory.detect and retry
} Prevention
- Use CompressorStreamFactory.detect() instead of hardcoding the format.
- Sniff magic bytes before decompressing untrusted input.
- Confirm file type out-of-band (`file`, content-type headers).
When it happens
Trigger: Passing a non-BZip2 file (plain text, gzip, zip, tar) to BZip2CompressorInputStream, or a stream whose position is not at the start of a .bz2 stream.
Common situations: Wrong decompressor chosen by extension guess; server sends a non-bzip2 response body; file was renamed to .bz2 without actually being compressed; reading a concatenated/next stream where only garbage remains.
Related errors
- Unexpected magic
- ADB command did not produce
- APK files backup is requested but no APK files have been…
- APPEND + TRUNCATE not allowed
- Array Size=" + array.length + ", offset=" + off + "…
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/b4a7747ab6446f23.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java:240
private boolean init(final boolean isFirstStream) throws IOException {
if (null == bin) {
throw new IOException("No InputStream");
}
if (!isFirstStream) {
bin.clearBitCache();
}
final int magic0 = readNextByte(this.bin);
if (magic0 == -1 && !isFirstStream) {
return false;
}
final int magic1 = readNextByte(this.bin);
final int magic2 = readNextByte(this.bin);
if (magic0 != 'B' || magic1 != 'Z' || magic2 != 'h') {
throw new IOException(isFirstStream
? "Stream is not in the BZip2 format"
: "Garbage after a valid BZip2 stream");
}
final int blockSize = readNextByte(this.bin);
if ((blockSize < '1') || (blockSize > '9')) {
throw new IOException("BZip2 block size is invalid");
}
this.blockSize100k = blockSize - '0';
this.computedCombinedCRC = 0;
return true;
}
private void initBlock() throws IOException {
final BitInputStream bin = this.bin;View on GitHub (pinned to 0152f468fc)