{"record":{"id":"20d4635f4f847f40","repo":"bumptech/glide","slug":"bufferedinputstream-is-closed","errorCode":null,"errorMessage":"BufferedInputStream is closed","messagePattern":"BufferedInputStream is closed","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/bumptech/glide/load/resource/bitmap/RecyclableBufferedInputStream.java","lineNumber":92,"sourceCode":"   * Returns an estimated number of bytes that can be read or skipped without blocking for more\n   * input. This method returns the number of bytes available in the buffer plus those available in\n   * the source stream, but see {@link InputStream#available} for important caveats.\n   *\n   * @return the estimated number of bytes available\n   * @throws IOException if this stream is closed or an error occurs\n   */\n  @Override\n  public synchronized int available() throws IOException {\n    // in could be invalidated by close().\n    InputStream localIn = in;\n    if (buf == null || localIn == null) {\n      throw streamClosed();\n    }\n    return count - pos + localIn.available();\n  }\n\n  private static IOException streamClosed() throws IOException {\n    throw new IOException(\"BufferedInputStream is closed\");\n  }\n\n  /**\n   * Reduces the mark limit to match the current buffer length to prevent the buffer from continuing\n   * to increase in size.\n   *\n   * <p>Subsequent calls to {@link #mark(int)} will be obeyed and may cause the buffer size to\n   * increase.\n   */\n  // Public API.\n  @SuppressWarnings(\"WeakerAccess\")\n  public synchronized void fixMarkLimit() {\n    marklimit = buf.length;\n  }\n\n  public synchronized void release() {\n    if (buf != null) {\n      byteArrayPool.put(buf);","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/bumptech/glide/blob/eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/RecyclableBufferedInputStream.java#L74-L110","documentation":"IOException thrown by RecyclableBufferedInputStream.available() after the stream has been closed (buf==null or underlying in==null). Closing releases the buffer; any subsequent read/available call indicates use-after-close of a recycled stream.","triggerScenarios":"Calling available() on a RecyclableBufferedInputStream after close() has been invoked. Common when an InputStream is fetched from a pool or wrapped and then closed by one decoder while another (or a retry) still references it.","commonSituations":"Reusing a cached/registry InputStream after the previous Glide decode pass closed it. Concurrent reads where one thread closes the stream. Custom ModelLoader/DataFetcher that returns a stream it then closes itself.","solutions":["Do not retain or reuse an InputStream after Glide has consumed it; fetch a fresh stream per load.","In custom DataFetchers, open a new stream in loadData() each time and let Glide close it.","Remove any explicit .close() on streams you hand to Glide.","If pooling buffers, ensure the wrapper stream is not also exposed to callers."],"exampleFix":"// before\nInputStream is = assetManager.open(path);\nGlide.with(ctx).load(is).into(img);\nis.available(); // closed by Glide already\n// after\n// Do not use the stream after passing it to Glide; reload if needed.\nGlide.with(ctx).load(new InputStreamLoader(assetManager, path)).into(img);","handlingStrategy":"validation","validationCode":"// Do not call available()/read() on a stream you gave to Glide.\n// If you must reuse, open a fresh stream:\nInputStream fresh() { return assetManager.open(path); }","typeGuard":null,"tryCatchPattern":"try { is.available(); }\ncatch (IOException closed) {\n  // stream was closed by Glide; reopen if still needed\n  is = reopen();\n}","preventionTips":["Treat any InputStream handed to Glide as owned by Glide.","Open fresh streams per load in custom DataFetchers.","Avoid sharing pooled streams across decoders."],"tags":["stream","io","lifecycle","android"],"backgroundTag":null,"analyzedSha":"eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a","analyzedAt":"2026-08-14T01:43:54.821Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}