HMCL-dev/HMCL · error · IOException

Cannot export a background directory as a theme-pack asset

Error message

Cannot export a background directory as a theme-pack asset: ${source}

What it means

Thrown by ThemePackManager when exporting a theme pack whose background resolves to a directory rather than an image file. Theme packs bundle backgrounds as ZIP entries under assets/wallpapers/, and a directory cannot be stored as a single asset. The manager fails fast before building the pack.

Solutions

  1. Change the theme's background image path to point at the actual image file inside the directory (e.g. dir/wallpaper.png instead of dir).
  2. If the directory contains the intended image, list its contents and pick a regular file; verify with Files.isRegularFile before exporting.
  3. Fix any symlink or path-join mistake that makes imagePath resolve to a directory instead of a file.

Example fix

// before
"background": { "imagePath": "/home/user/wallpapers/" }
// after
"background": { "imagePath": "/home/user/wallpapers/sunset.png" }
Defensive patterns

Strategy: validation

Validate before calling

Path p = Path.of(configuredPath).toAbsolutePath().normalize();
if (Files.isDirectory(p)) throw new IllegalArgumentException("background must be an image file, not a directory: " + p);
if (!Files.isRegularFile(p)) throw new IllegalArgumentException("background image missing: " + p);

Prevention

When it happens

Trigger: Calling the theme-pack export flow with a background whose imagePath() points at a directory (Files.isDirectory(source) is true after toAbsolutePath().normalize()).

Common situations: A theme JSON/manifest configured with a background path that accidentally points at a folder (e.g. an extracted wallpaper directory instead of the wallpaper file inside it); a misconfigured custom-background setting where the user selected a directory; a symlink resolving to a directory.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManager.java:1483

    }

    /// Creates the image background source for the resolved current background image.
    private static ThemeBackground.Image createCurrentImageBackgroundSource(
            List<ThemePackAsset> assets,
            ResolvedBackground background) throws IOException {
        @Nullable ThemePackResource imageResource = background.imageResource();
        if (imageResource != null) {
            assets.add(new ThemePackAsset(imageResource, imageResource.name()));
            return new ThemeBackground.Image(imageResource.name());
        }

        @Nullable Path imagePath = background.imagePath();
        if (imagePath == null) {
            throw new IOException("Theme background image path is not configured");
        }
        Path source = imagePath.toAbsolutePath().normalize();
        if (Files.isDirectory(source)) {
            throw new IOException("Cannot export a background directory as a theme-pack asset: " + source);
        }
        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)) {

View on GitHub (pinned to 24702dc5a0)