bumptech/glide · error · HttpException

Bad redirect url: {redirectUrlString}

Error message

Bad redirect url: {redirectUrlString}

What it means

After extracting a non-empty Location header from a redirect response, HttpUrlFetcher attempts to construct a java.net.URL from it (resolved relative to the current URL). If the Location header contains a syntactically invalid URL, the MalformedURLException is caught and re-thrown as an HttpException with the bad URL string and the redirect status code.

Source

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

    }

    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);
      }
    }
  }

  private static int getHttpStatusCodeOrInvalid(HttpURLConnection urlConnection) {
    try {

View on GitHub (pinned to eb14a895d8)

Solutions

  1. Fix the server to emit properly encoded, valid URLs in the Location header
  2. Provide the final canonical image URL directly to Glide
  3. Handle the HttpException in a RequestListener and use a fallback image

Example fix

// before
Glide.with(context).load(problematicRedirectUrl).into(imageView);
// after — use the known-good final URL
Glide.with(context)
  .load(canonicalImageUrl)
  .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("Bad redirect url")) {
          Log.w(TAG, "Malformed redirect URL from server 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 a Location header with illegal characters, spaces, or malformed scheme. Relative redirect path that cannot be resolved against the base URL. Server sends a Location value with unescaped Unicode characters.

Common situations: Servers that generate redirect URLs dynamically without proper encoding. Internationalized domain names or paths with special characters. Proxy servers that mangle the Location header.

Related errors


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