MuntashirAkon/AppManager · error · IOException

Stream closed

Error message

Stream closed

What it means

BZip2CompressorInputStream.read() throws IOException("Stream closed") when read() is called after the stream has been closed (internal bin reference is null). InputStream.close() nulls the underlying decoder, and any subsequent read fails.

Source

Thrown at app/src/main/java/org/apache/commons/compress/compressors/bzip2/BZip2CompressorInputStream.java:125

     *             if {@code in == null}, the stream content is malformed, or an I/O error occurs.
     */
    public BZip2CompressorInputStream(final InputStream in, final boolean decompressConcatenated) throws IOException {
        this.bin = new BitInputStream(in == System.in ? new CloseShieldFilterInputStream(in) : in,
                ByteOrder.BIG_ENDIAN);
        this.decompressConcatenated = decompressConcatenated;

        init(true);
        initBlock();
    }

    @Override
    public int read() throws IOException {
        if (this.bin != null) {
            final int r = read0();
            count(r < 0 ? -1 : 1);
            return r;
        }
        throw new IOException("Stream closed");
    }

    /*
     * (non-Javadoc)
     *
     * @see java.io.InputStream#read(byte[], int, int)
     */
    @Override
    public int read(final byte[] dest, final int offs, final int len)
            throws IOException {
        if (offs < 0) {
            throw new IndexOutOfBoundsException("offs(" + offs + ") < 0.");
        }
        if (len < 0) {
            throw new IndexOutOfBoundsException("len(" + len + ") < 0.");
        }
        if (offs + len > dest.length) {
            throw new IndexOutOfBoundsException("offs(" + offs + ") + len("

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Don't read after close(); restructure code so all reads occur inside the try-with-resources block
  2. Remove duplicate/extra close() calls on the same stream
  3. Reopen a new BZip2CompressorInputStream from the source if more data is needed
  4. Guard concurrent access: one owner per stream, or synchronize close/read

Example fix

// before
BZip2CompressorInputStream s = new BZip2CompressorInputStream(fis);
s.close();
int b = s.read(); // IOException: Stream closed
// after
try (BZip2CompressorInputStream s = new BZip2CompressorInputStream(fis)) {
    int b = s.read();
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    int b = bzipStream.read();
} catch (IOException e) {
    if ("Stream closed".equals(e.getMessage())) {
        throw new IllegalStateException("Read attempted after close(); reopen the stream", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling read() (single-byte or array variants) on a BZip2CompressorInputStream after close(); often from double-close followed by read, or sharing one stream across threads after one closed it.

Common situations: Try-with-resources accidentally covering code that re-reads the stream; caching the stream for later use after a close; concurrent access where one consumer closes early.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/60b28cfc69b46bff. Report an issue: GitHub.