bumptech/glide · error · HttpException

Received empty or null redirect url

Error message

Received empty or null redirect url

What it means

When the server returns a 3xx redirect status code, HttpUrlFetcher reads the Location header to determine the redirect target. If the Location header is empty or missing (TextUtils.isEmpty returns true), the redirect response is malformed and Glide cannot follow it, so it throws an HttpException with the redirect status code.

Source

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

      urlConnection.connect();
      // Set the stream so that it's closed in cleanup to avoid resource leaks. See #2352.
      stream = urlConnection.getInputStream();
    } catch (IOException e) {
      throw new HttpException(
          "Failed to connect or obtain data", getHttpStatusCodeOrInvalid(urlConnection), e);
    }

    if (isCancelled) {
      return null;
    }

    final int statusCode = getHttpStatusCodeOrInvalid(urlConnection);
    if (isHttpOk(statusCode)) {
      return getStreamForSuccessfulRequest(urlConnection);
    } else if (isHttpRedirect(statusCode)) {
      String redirectUrlString = urlConnection.getHeaderField(REDIRECT_HEADER_FIELD);
      if (TextUtils.isEmpty(redirectUrlString)) {
        throw new HttpException("Received empty or null redirect url", statusCode);
      }
      URL redirectUrl;
      try {
        redirectUrl = new URL(url, redirectUrlString);
      } catch (MalformedURLException e) {
        throw new HttpException("Bad redirect url: " + redirectUrlString, statusCode, e);
      }
      // Closing the stream specifically is required to avoid leaking ResponseBodys in addition
      // to disconnecting the url connection below. See #2352.
      cleanup();
      return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
    } else if (statusCode == INVALID_STATUS_CODE) {
      throw new HttpException(statusCode);
    } else {
      try {
        throw new HttpException(urlConnection.getResponseMessage(), statusCode);
      } catch (IOException e) {
        throw new HttpException("Failed to get a response message", statusCode, e);

View on GitHub (pinned to eb14a895d8)

Solutions

  1. Fix the server to always include a valid Location header on 3xx responses
  2. Provide the direct (non-redirecting) image URL to Glide
  3. Handle the HttpException in RequestListener and show a fallback image

Example fix

// before
Glide.with(context).load(redirectingUrl).into(imageView);
// after — use direct URL and handle failure
Glide.with(context)
  .load(directImageUrl)
  .error(R.drawable.placeholder)
  .into(imageView);
Defensive patterns

Strategy: fallback

Try / catch

Glide.with(context)
  .load(url)
  .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("empty or null redirect")) {
          Log.w(TAG, "Server sent redirect without Location header for " + model);
        }
      }
      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 returns 301 Moved Permanently or 302 Found but omits or sends a blank Location header. A reverse proxy strips the Location header. A server bug returns a redirect status without the corresponding header.

Common situations: Misconfigured web servers or CDNs. Custom server-side redirect logic that forgets to set the Location header. API gateways that proxy redirects incorrectly.

Related errors


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