{"record":{"id":"a1fae4d157b5a8a1","repo":"bumptech/glide","slug":"failed-to-obtain-inputstream","errorCode":null,"errorMessage":"Failed to obtain InputStream","messagePattern":"Failed to obtain InputStream","errorType":"http","errorClass":"HttpException","httpStatus":null,"severity":"error","filePath":"library/src/main/java/com/bumptech/glide/load/data/HttpUrlFetcher.java","lineNumber":190,"sourceCode":"  // Referencing constants is less clear than a simple static method.\n  private static boolean isHttpRedirect(int statusCode) {\n    return statusCode / 100 == 3;\n  }\n\n  private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection)\n      throws HttpException {\n    try {\n      if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {\n        int contentLength = urlConnection.getContentLength();\n        stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);\n      } else {\n        if (Log.isLoggable(TAG, Log.DEBUG)) {\n          Log.d(TAG, \"Got non empty content encoding: \" + urlConnection.getContentEncoding());\n        }\n        stream = urlConnection.getInputStream();\n      }\n    } catch (IOException e) {\n      throw new HttpException(\n          \"Failed to obtain InputStream\", getHttpStatusCodeOrInvalid(urlConnection), e);\n    }\n    return stream;\n  }\n\n  @Override\n  public void cleanup() {\n    if (stream != null) {\n      try {\n        stream.close();\n      } catch (IOException e) {\n        // Ignore\n      }\n    }\n    if (urlConnection != null) {\n      urlConnection.disconnect();\n    }\n    urlConnection = null;","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/bumptech/glide/blob/eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a/library/src/main/java/com/bumptech/glide/load/data/HttpUrlFetcher.java#L172-L208","documentation":"After a successful 200 OK response, HttpUrlFetcher calls getStreamForSuccessfulRequest to obtain the InputStream from the connection, wrapping it with ContentLengthInputStream for progress tracking. If getInputStream() throws an IOException at this stage, it is wrapped in an HttpException with the message 'Failed to obtain InputStream' and the available status code. This means the server returned 200 but the data stream could not be read.","triggerScenarios":"Server sends a 200 OK status line but drops the connection before sending the response body. Network interruption after headers are received. Server-side crash mid-response. Content-Length mismatch causing the stream wrapper to fail.","commonSituations":"Large image downloads on unstable connections that drop after the initial handshake. Servers that flush headers then crash. Mobile network handoff between cell towers mid-download. Reverse proxy timeouts during large file transfer.","solutions":["Retry the load; intermittent stream failures are often transient","Use OkHttp integration with Glide for better connection pooling and retry behavior","Reduce image size at the source to shorten transfer time and reduce drop probability","Add .error() placeholder and implement RequestListener for graceful degradation"],"exampleFix":"// before\nGlide.with(context).load(largeImageUrl).into(imageView);\n// after — add thumbnail for progressive feel and error fallback\nGlide.with(context)\n  .load(largeImageUrl)\n  .thumbnail(0.1f)\n  .error(R.drawable.placeholder)\n  .into(imageView);","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"Glide.with(context)\n  .load(url)\n  .thumbnail(0.1f)\n  .error(R.drawable.placeholder)\n  .listener(new RequestListener<Drawable>() {\n    @Override public boolean onLoadFailed(GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {\n      for (Throwable cause : e.getRootCauses()) {\n        if (cause instanceof HttpException && cause.getMessage().contains(\"Failed to obtain InputStream\")) {\n          Log.w(TAG, \"Stream dropped after 200 OK for \" + model);\n          // Transient — consider returning true to retry\n        }\n      }\n      return false;\n    }\n    @Override public boolean onResourceReady(Drawable r, Object m, Target<Drawable> t, DataSource d, boolean i) { return false; }\n  })\n  .into(imageView);","preventionTips":["Retry loads that fail after a 200 OK as they are typically transient","Integrate OkHttp for better streaming reliability","Reduce image file sizes server-side to shorten transfer times","Use .thumbnail() for progressive loading on large images"],"tags":["glide","http","stream","network"],"backgroundTag":null,"analyzedSha":"eb14a895d8f866e6a08c3e19d50ea3bd2c12c20a","analyzedAt":"2026-08-14T01:43:54.821Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}