{"record":{"id":"251f91b39866b35a","repo":"HMCL-dev/HMCL","slug":"theme-pack-does-not-contain","errorCode":null,"errorMessage":"Theme pack does not contain ","messagePattern":"Theme pack does not contain ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManager.java","lineNumber":388,"sourceCode":"        Path normalizedFile = file.toAbsolutePath().normalize();\n        try {\n            if (Files.isDirectory(normalizedFile)) {\n                Path manifestFile = normalizedFile.resolve(ThemePackExporter.MANIFEST_ENTRY);\n                if (!Files.isRegularFile(manifestFile)) {\n                    throw new IOException(\"Theme pack directory does not contain \" + ThemePackExporter.MANIFEST_ENTRY);\n                }\n\n                ThemePackManifest manifest = JsonUtils.fromJsonFile(manifestFile, ThemePackManifest.class);\n                if (manifest == null) {\n                    throw new JsonParseException(\"Manifest is null\");\n                }\n                return new LoadedThemePack(normalizedFile, manifest);\n            }\n\n            try (var reader = new ZipArchiveReader(normalizedFile)) {\n                var manifestEntry = reader.getEntry(ThemePackExporter.MANIFEST_ENTRY);\n                if (manifestEntry == null || manifestEntry.isDirectory()) {\n                    throw new IOException(\"Theme pack does not contain \" + ThemePackExporter.MANIFEST_ENTRY);\n                }\n\n                ThemePackManifest manifest;\n                try (var inputStream = reader.getInputStream(manifestEntry)) {\n                    manifest = JsonUtils.fromNonNullJsonFully(inputStream, ThemePackManifest.class);\n                }\n                return new LoadedThemePack(normalizedFile, manifest);\n            }\n        } catch (JsonParseException | IllegalArgumentException e) {\n            throw new IOException(\"Invalid theme-pack manifest\", e);\n        }\n    }\n\n    /// Loads built-in theme pack manifests from launcher resources.\n    private static @Unmodifiable List<InstalledThemePack> loadBuiltinThemePacks() {\n        ArrayList<InstalledThemePack> themePacks = new ArrayList<>();\n        for (String id : BUILTIN_THEME_PACK_IDS) {\n            try {","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManager.java#L370-L406","documentation":"Thrown by ThemePackManager.load when the target file is not a directory and the zip archive it opens has no regular (non-directory) entry for the manifest (theme.json). A packaged theme pack must ship the manifest, so loading aborts with an IOException.","triggerScenarios":"Calling ThemePackManager.load on a zip file that lacks a theme.json entry, or where the manifestEntry exists but manifestEntry.isDirectory() is true (a folder entry named like the manifest).","commonSituations":"Renaming a resource pack or skin archive to a theme-pack extension, zipping a theme folder incorrectly so the manifest is under an extra top-level folder, or archives created by tools that stored a directory entry named theme.json.","solutions":["Repackage the zip so theme.json sits at the archive root (zip the contents, not the parent folder).","Verify with a zip tool that a regular file entry named theme.json exists at the root.","Use ThemePackExporter.export to produce a correctly structured pack archive.","Confirm the file actually is a theme pack and not another launcher archive format."],"exampleFix":"// before (zip layout)\nmytheme/background.png\n// after (zip layout)\ntheme.json\nbackground.png","handlingStrategy":"validation","validationCode":"try (var reader = new ZipArchiveReader(zip)) {\n    var e = reader.getEntry(\"theme.json\");\n    if (e == null || e.isDirectory()) throw new IllegalArgumentException(\"Zip has no root theme.json\");\n}","typeGuard":null,"tryCatchPattern":"try { manager.load(zipPath); } catch (IOException e) { if (e.getMessage().startsWith(\"Theme pack does not contain\")) repackageWithRootManifest(); else throw e; }","preventionTips":["Zip the pack contents so theme.json is at the archive root","Inspect the archive with a zip listing tool before distributing","Produce packs with ThemePackExporter instead of manual zipping"],"tags":["io","theme-pack","zip","manifest","file-not-found"],"backgroundTag":"file-not-found","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}