HMCL-dev/HMCL · error · JsonParseException

Manifest is null

Error message

Manifest is null

What it means

Thrown by ThemePackManager.load when JsonUtils.fromJsonFile returns null while deserializing the theme pack manifest. Although the manifest file exists, its parsed result was null, which the loader treats as an unrecoverable parse failure rather than silently returning no pack.

Solutions

  1. Open theme.json and restore valid manifest JSON (at minimum the required manifest fields).
  2. Re-export the theme pack to regenerate a correct manifest.
  3. Check the file is non-empty and does not literally contain "null".
  4. Validate the JSON syntax with a linter before retrying the load.

Example fix

// before (theme.json)
null
// after (theme.json)
{"name": "My Theme", "author": "Alice"}
Defensive patterns

Strategy: validation

Validate before calling

Path manifest = dir.resolve("theme.json");
String text = Files.readString(manifest);
if (text.isBlank() || text.strip().equals("null")) throw new IllegalStateException("Manifest is empty/null");

Try / catch

try { manager.load(path); } catch (JsonParseException e) { if ("Manifest is null".equals(e.getMessage())) regenerateManifest(); throw e; }

Prevention

When it happens

Trigger: Loading a directory theme pack whose theme.json parses to null — e.g. a file containing only whitespace/null — via JsonUtils.fromJsonFile(manifestFile, ThemePackManifest.class).

Common situations: theme.json accidentally saved as empty or containing the literal text null, editors that truncated the file during a crash, or generation scripts writing a null placeholder.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

    /// Loads and parses a theme-pack file or unpacked theme-pack directory.
    ///
    /// @param file the theme-pack file or directory
    /// @return the loaded theme pack
    /// @throws IOException if the file cannot be read or the manifest is invalid
    public static LoadedThemePack load(Path file) throws IOException {
        Objects.requireNonNull(file);

        Path normalizedFile = file.toAbsolutePath().normalize();
        try {
            if (Files.isDirectory(normalizedFile)) {
                Path manifestFile = normalizedFile.resolve(ThemePackExporter.MANIFEST_ENTRY);
                if (!Files.isRegularFile(manifestFile)) {
                    throw new IOException("Theme pack directory does not contain " + ThemePackExporter.MANIFEST_ENTRY);
                }

                ThemePackManifest manifest = JsonUtils.fromJsonFile(manifestFile, ThemePackManifest.class);
                if (manifest == null) {
                    throw new JsonParseException("Manifest is null");
                }
                return new LoadedThemePack(normalizedFile, manifest);
            }

            try (var reader = new ZipArchiveReader(normalizedFile)) {
                var manifestEntry = reader.getEntry(ThemePackExporter.MANIFEST_ENTRY);
                if (manifestEntry == null || manifestEntry.isDirectory()) {
                    throw new IOException("Theme pack does not contain " + ThemePackExporter.MANIFEST_ENTRY);
                }

                ThemePackManifest manifest;
                try (var inputStream = reader.getInputStream(manifestEntry)) {
                    manifest = JsonUtils.fromNonNullJsonFully(inputStream, ThemePackManifest.class);
                }
                return new LoadedThemePack(normalizedFile, manifest);
            }
        } catch (JsonParseException | IllegalArgumentException e) {
            throw new IOException("Invalid theme-pack manifest", e);

View on GitHub (pinned to 24702dc5a0)