HMCL-dev/HMCL · error · IOException

Cannot delete a built-in theme pack:

Error message

Cannot delete a built-in theme pack: 

What it means

ThemePackManager.uninstall(InstalledThemePack) refuses to remove packs flagged as built-in (bundled with the launcher resources). It throws this IOException carrying the pack's manifest id, because built-in packs have no deletable on-disk file managed by the launcher.

Solutions

  1. Check themePack.builtin() before calling uninstall and skip/exclude built-in packs from deletion.
  2. If the goal is to stop using a built-in pack, switch the selected theme to another pack instead of uninstalling it.
  3. Filter the pack list with p -> !p.builtin() wherever uninstall/delete actions are exposed.

Example fix

// before
for (InstalledThemePack p : packs) ThemePackManager.uninstall(p);
// after
for (InstalledThemePack p : packs) {
    if (!p.builtin()) ThemePackManager.uninstall(p);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (pack.builtin()) return; // nothing to delete; switch theme instead

Type guard

static boolean uninstallable(InstalledThemePack p) {
    return !p.builtin() && p.file() != null;
}

Try / catch

try {
    ThemePackManager.uninstall(pack);
} catch (IOException e) {
    if (e.getMessage().startsWith("Cannot delete a built-in theme pack")) {
    // built-in packs are immutable; ignore or inform the user
    }
}

Prevention

When it happens

Trigger: Calling ThemePackManager.uninstall() with an InstalledThemePack whose builtin() flag is true, i.e. any pack returned by loadBuiltinThemePacks() rather than installed into THEME_PACKS_DIRECTORY/USER_THEME_PACKS_DIRECTORY.

Common situations: UI code iterating all installed packs (including built-ins) and offering a delete action without filtering; scripted cleanup that deletes every pack in the list.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

                deleteIfExists(temporaryFile);
            } catch (IOException suppressed) {
                e.addSuppressed(suppressed);
            }
            throw e;
        }
    }

    /// Removes an installed theme pack from a managed theme-pack directory.
    ///
    /// If the removed package is currently selected, the stored theme reference is cleared.
    ///
    /// @param themePack the installed theme pack to remove
    /// @throws IOException if the installed package cannot be removed
    public static void uninstall(InstalledThemePack themePack) throws IOException {
        Objects.requireNonNull(themePack);

        if (themePack.builtin()) {
            throw new IOException("Cannot delete a built-in theme pack: " + themePack.manifest().id());
        }

        @Nullable Path file = themePack.file();
        if (file == null) {
            throw new IOException("Theme pack does not have a local file: " + themePack.manifest().id());
        }

        Path targetFile = file.toAbsolutePath().normalize();
        Path localDirectory = THEME_PACKS_DIRECTORY.toAbsolutePath().normalize();
        Path userDirectory = USER_THEME_PACKS_DIRECTORY.toAbsolutePath().normalize();
        boolean localThemePack = targetFile.startsWith(localDirectory) && !targetFile.equals(localDirectory);
        boolean userThemePack = targetFile.startsWith(userDirectory) && !targetFile.equals(userDirectory);
        if (!localThemePack && !userThemePack) {
            throw new IOException("Theme-pack file is outside the managed directory: " + targetFile);
        }

        deleteIfExists(targetFile);

View on GitHub (pinned to 24702dc5a0)