HMCL-dev/HMCL · error · java.io.IOException

Redirected to not http URI

Error message

Redirected to not http URI: <target>

What it means

After resolving a redirect's Location header, FetchTask.downloadHttp() validates the resulting URI is an HTTP(S) URI before continuing. This IOException is thrown when a redirect points to a non-http(s) scheme (e.g. ftp:, file:, or a malformed URI), which the downloader refuses to follow for safety.

Solutions

  1. Locate the redirecting host and correct its Location header to an http(s) URL
  2. Use the final direct http(s) URL as the download source
  3. Treat the host as untrusted (possible open redirect) and blocklist it
  4. Catch the IOException and route the download through a different mirror
Defensive patterns

Strategy: validation

Validate before calling

URI location = currentURI.resolve(NetworkUtils.encodeLocation(rawLocation));
if (!NetworkUtils.isHttpUri(location))
    throw new IllegalArgumentException("Refusing non-http redirect: " + location);

Type guard

static boolean isSafeRedirect(URI target) {
    String s = target.getScheme();
    return "http".equals(s) || "https".equals(s);
}

Try / catch

try {
    fetchTask.run();
} catch (IOException e) {
    if (e.getMessage().startsWith("Redirected to not http URI")) blocklistHostAndRetry();
    else throw e;
}

Prevention

When it happens

Trigger: A server's Location header redirects to ftp://, file://, data:, or an unparseable URI — often from misconfigured redirects or malicious/open-redirect endpoints.

Common situations: Legacy mirrors redirecting to FTP; misconfigured CDNs emitting relative paths that resolve to invalid URIs; security-sensitive environments where redirect targets must be constrained.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/8a73588cce414b93. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java:363

                                }
                            }

                            if (responseCode >= 300 && responseCode <= 308 && responseCode != 306 && responseCode != 304) {
                                if (redirects == null) {
                                    redirects = new ArrayList<>();
                                } else if (redirects.size() >= 20) {
                                    throw new IOException("Too much redirects");
                                }

                                String location = connection.getHeaderField("Location");
                                if (StringUtils.isBlank(location))
                                    throw new IOException("Redirected to an empty location");

                                URI target = currentURI.resolve(NetworkUtils.encodeLocation(location));
                                redirects.add(target);

                                if (!NetworkUtils.isHttpUri(target))
                                    throw new IOException("Redirected to not http URI: " + target);

                                currentURI = target;
                            } else {
                                keepConnection = true;
                                break;
                            }
                        } finally {
                            if (!keepConnection && connection != null) {
                                closeHttpConnection(connection);
                                connection = null;
                            }
                        }
                    } while (true);

                    InputStream inputStream = null;
                    boolean responseBodyConsumed = false;
                    try {
                        if (resumeRequested && responseCode == 416) {

View on GitHub (pinned to 24702dc5a0)