HMCL-dev/HMCL · error · IOException
Theme background URL must be HTTP or HTTPS
Error message
Theme background URL must be HTTP or HTTPS: ${url} What it means
Thrown by ThemePackManager when resolving a network background whose URL scheme is not HTTP or HTTPS (e.g. ftp:, file:, data:). The downloader only supports HttpURLConnection-based fetching, so non-HTTP(S) URIs are rejected before any download is attempted.
Solutions
- Replace the URL with an http:// or https:// link to the image.
- If the image is local, use a background imagePath/file background instead of networkImageUrl.
- If you need data-URI backgrounds, download the image and reference it as a local asset first.
Example fix
// before
"background": { "url": "file:///home/user/wall.png" }
// after
"background": { "url": "https://example.com/wall.png" } Defensive patterns
Strategy: validation
Validate before calling
URI uri = URI.create(url);
if (!"http".equalsIgnoreCase(uri.getScheme()) && !"https".equalsIgnoreCase(uri.getScheme())) {
throw new IllegalArgumentException("background url must be http(s): " + url);
} Type guard
static boolean isHttpUrl(String url) {
try {
String s = URI.create(url).getScheme();
return "http".equalsIgnoreCase(s) || "https".equalsIgnoreCase(s);
} catch (IllegalArgumentException e) { return false; }
} Prevention
- Only use http:// or https:// links for network backgrounds.
- Use local file backgrounds for images stored on disk instead of file:// URLs.
When it happens
Trigger: Setting a theme background with networkImageUrl set to a non-HTTP(S) URI; NetworkUtils.toURI(url) parses it but NetworkUtils.isHttpUri(uri) returns false.
Common situations: Pasting a file:// or data:image/... URL into a theme's background.url field; using an ftp:// mirror link; authoring a manifest by hand with a localhost or custom-scheme URL.
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
- Invalid URL:
- Theme-pack asset entry is empty
- Theme-pack asset entry must be relative:
- Theme-pack asset entry must be under assets/:
- Theme-pack asset entry must be a file:
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/6a8b6cb0c8f3181b.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManager.java:1502
}
if (!Files.isRegularFile(source)) {
throw new IOException("Theme background image does not exist: " + source);
}
String entryName = "assets/wallpapers/" + sanitizePathSegment(source.getFileName().toString());
assets.add(new ThemePackAsset(source, entryName));
return new ThemeBackground.Image(entryName);
}
/// Downloads the current network background and exports it as a theme-pack image asset.
private static ThemeBackground.Image createCurrentNetworkBackgroundSource(
List<ThemePackAsset> assets,
List<Path> temporaryFiles,
ResolvedBackground background) throws IOException {
String url = requireNonBlank(background.networkImageUrl(), "background.url");
URI uri = NetworkUtils.toURI(url);
if (!NetworkUtils.isHttpUri(uri)) {
throw new IOException("Theme background URL must be HTTP or HTTPS: " + url);
}
String entryName = "assets/wallpapers/" + networkBackgroundAssetName(uri);
if (background.networkImageCachePolicy() == NetworkBackgroundImageCachePolicy.ENABLED) {
try {
@Nullable Path cachedFile = new CacheFileTask(uri).run();
if (cachedFile != null && Files.isRegularFile(cachedFile)) {
assets.add(new ThemePackAsset(cachedFile, entryName));
return new ThemeBackground.Image(entryName);
}
} catch (Exception e) {
LOG.warning("Failed to cache theme background, falling back to direct download: " + uri, e);
}
}
Path temporaryFile = Files.createTempFile("hmcl-theme-background-", ".tmp");
boolean success = false;
try {View on GitHub (pinned to 24702dc5a0)