HMCL-dev/HMCL · error · IOException

Theme-pack asset is missing

Error message

Theme-pack asset is missing: ${entryName}

What it means

ZipFileThemePackResource.openStream opens the pack's zip and looks up entryName; when the entry is absent or is a directory, it throws IOException "Theme-pack asset is missing: <entryName>". This means the theme pack does not physically contain the requested asset.

Solutions

  1. Verify the asset exists in the zip at exactly the path the manifest references (case-sensitive).
  2. Add the missing file to the zip and repack the theme pack.
  3. If the manifest path is wrong (extra directory prefix), correct the manifest entry path.

Example fix

// before
"wallpaper": "wallpaper.png"   // file is actually at assets/wallpaper.png
// after
"wallpaper": "assets/wallpaper.png"
Defensive patterns

Strategy: try-catch

Validate before calling

try (ZipArchiveReader zip = new ZipArchiveReader(zipFile, UTF_8)) { boolean present = zip.getEntry(entryName) != null && !zip.getEntry(entryName).isDirectory(); }

Try / catch

try (InputStream in = resource.openStream()) { use(in); } catch (IOException e) { useDefaultWallpaper(); }

Prevention

When it happens

Trigger: Requesting a wallpaper/font asset path that is not inside the theme-pack zip; the entry exists but is a directory entry; manifest references an asset that was never packaged or was deleted.

Common situations: Manifest edited to reference wallpaper.png but the zip contains images/wallpaper.jpg; repacking the zip without the asset folder; path case mismatch inside the zip.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackResource.java:122

            zipFile = Objects.requireNonNull(zipFile).toAbsolutePath().normalize();
            entryName = ThemePackAsset.normalizeEntryName(entryName);
        }

        /// Returns the zip entry name.
        @Override
        public String name() {
            return entryName;
        }

        /// Opens the zip entry and closes the zip file when the returned stream is closed.
        @Override
        public InputStream openStream() throws IOException {
            ZipArchiveReader zip = new ZipArchiveReader(zipFile, StandardCharsets.UTF_8);
            boolean success = false;
            try {
                ZipArchiveEntry entry = zip.getEntry(entryName);
                if (entry == null || entry.isDirectory()) {
                    throw new IOException("Theme-pack asset is missing: " + entryName);
                }
                InputStream input = zip.getInputStream(entry);
                success = true;
                return new ZipEntryInputStream(input, zip);
            } finally {
                if (!success) {
                    zip.close();
                }
            }
        }
    }

    /// A resource stored in launcher-bundled classpath resources.
    ///
    /// @param resourcePath the classpath resource path
    /// @param entryName    the theme-pack entry name
    @NotNullByDefault
    record Builtin(String resourcePath, String entryName) implements ThemePackResource {

View on GitHub (pinned to 24702dc5a0)