bumptech/glide · error · HttpException

Failed to obtain InputStream

Error message

Failed to obtain InputStream

What it means

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.

Source

Thrown at library/src/main/java/com/bumptech/glide/load/data/HttpUrlFetcher.java:190

  // Referencing constants is less clear than a simple static method.
  private static boolean isHttpRedirect(int statusCode) {
    return statusCode / 100 == 3;
  }

  private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection)
      throws HttpException {
    try {
      if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
        int contentLength = urlConnection.getContentLength();
        stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);
      } else {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
          Log.d(TAG, "Got non empty content encoding: " + urlConnection.getContentEncoding());
        }
        stream = urlConnection.getInputStream();
      }
    } catch (IOException e) {
      throw new HttpException(
          "Failed to obtain InputStream", getHttpStatusCodeOrInvalid(urlConnection), e);
    }
    return stream;
  }

  @Override
  public void cleanup() {
    if (stream != null) {
      try {
        stream.close();
      } catch (IOException e) {
        // Ignore
      }
    }
    if (urlConnection != null) {
      urlConnection.disconnect();
    }
    urlConnection = null;

View on GitHub (pinned to eb14a895d8)

Solutions

  1. Retry the load; intermittent stream failures are often transient
  2. Use OkHttp integration with Glide for better connection pooling and retry behavior
  3. Reduce image size at the source to shorten transfer time and reduce drop probability
  4. Add .error() placeholder and implement RequestListener for graceful degradation

Example fix

// before
Glide.with(context).load(largeImageUrl).into(imageView);
// after — add thumbnail for progressive feel and error fallback
Glide.with(context)
  .load(largeImageUrl)
  .thumbnail(0.1f)
  .error(R.drawable.placeholder)
  .into(imageView);
Defensive patterns

Strategy: retry

Try / catch

Glide.with(context)
  .load(url)
  .thumbnail(0.1f)
  .error(R.drawable.placeholder)
  .listener(new RequestListener<Drawable>() {
    @Override public boolean onLoadFailed(GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
      for (Throwable cause : e.getRootCauses()) {
        if (cause instanceof HttpException && cause.getMessage().contains("Failed to obtain InputStream")) {
          Log.w(TAG, "Stream dropped after 200 OK for " + model);
          // Transient — consider returning true to retry
        }
      }
      return false;
    }
    @Override public boolean onResourceReady(Drawable r, Object m, Target<Drawable> t, DataSource d, boolean i) { return false; }
  })
  .into(imageView);

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of bumptech/glide@eb14a895d8 (2026-08-14). Data as JSON: /api/errors/a1fae4d157b5a8a1. Report an issue: GitHub.