HMCL-dev/HMCL · error · IOException

Installed theme-pack asset is missing:

Error message

Installed theme-pack asset is missing: 

What it means

When the theme-pack location is a directory, resolveInstalledAsset resolves the normalized entry inside it and requires the target to be a regular file. If the resolved asset path does not exist or is not a regular file (e.g. a directory), it throws this IOException naming the entry.

Solutions

  1. Verify the asset exists at <packDir>/<entryName> and is a regular file before resolving.
  2. Reinstall or re-export the theme pack so the manifest and its assets are in sync.
  3. Fix entry-name case to match the on-disk file, especially on case-sensitive filesystems.

Example fix

// before
resolveInstalledAsset(location, manifest.getBackgroundEntry());
// after
Path asset = Path.of(packDir, entry);
if (Files.isRegularFile(asset)) resolveInstalledAsset(location, entry);
Defensive patterns

Strategy: validation

Validate before calling

Path asset = Path.of(packDir, ThemePackAsset.normalizeEntryName(entryName));
if (!Files.isRegularFile(asset)) {
    // skip or re-export the pack; do not resolve
}

Try / catch

try {
    ThemePackManager.resolveInstalledAsset(location, entry);
} catch (IOException e) {
    if (e.getMessage().startsWith("Installed theme-pack asset is missing")) {
    // fall back to a default asset or prompt reinstall
    }
}

Prevention

When it happens

Trigger: Calling resolveInstalledAsset() on a directory-installed pack where the referenced entry is absent from the unpacked directory, was deleted, or resolves to a subdirectory rather than a file.

Common situations: A manifest referencing assets renamed in a newer pack version; the user manually deleting files from the unpacked pack directory; case-sensitivity mismatches on Linux after a pack created on Windows.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — 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/452982eb312dc594. Report an issue: GitHub.

Appendix: source

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

    public static ThemePackResource resolveInstalledAsset(ThemePackLocation location, String entryName) throws IOException {
        Objects.requireNonNull(location);
        String normalizedEntryName = ThemePackAsset.normalizeEntryName(entryName);
        if (location instanceof ThemePackLocation.Builtin builtin) {
            return resolveBuiltinAsset(builtin, normalizedEntryName);
        }

        @Nullable Path file = location.file();
        if (file == null) {
            throw new IOException("Theme pack location has no readable file: " + location);
        }
        Path installedFile = file.toAbsolutePath().normalize();
        if (Files.isDirectory(installedFile)) {
            Path assetFile = installedFile.resolve(normalizedEntryName).normalize();
            if (!assetFile.startsWith(installedFile)) {
                throw new IOException("Theme-pack asset escapes the installed directory: " + normalizedEntryName);
            }
            if (!Files.isRegularFile(assetFile)) {
                throw new IOException("Installed theme-pack asset is missing: " + normalizedEntryName);
            }
            return new ThemePackResource.File(assetFile, normalizedEntryName);
        }
        if (!Files.isRegularFile(installedFile)) {
            throw new IOException("Installed theme-pack file is missing: " + installedFile);
        }

        try (ZipArchiveReader zipFile = new ZipArchiveReader(installedFile, StandardCharsets.UTF_8)) {
            ZipArchiveEntry entry = zipFile.getEntry(normalizedEntryName);
            if (entry == null || entry.isDirectory()) {
                throw new IOException("Installed theme-pack asset is missing: " + normalizedEntryName);
            }
        }
        return new ThemePackResource.Zip(installedFile, normalizedEntryName);
    }

    /// Resolves one asset stored in a bundled theme pack.
    private static ThemePackResource resolveBuiltinAsset(ThemePackLocation.Builtin builtin, String entryName) throws IOException {

View on GitHub (pinned to 24702dc5a0)