{"record":{"id":"851c1560d8acc0c5","repo":"HMCL-dev/HMCL","slug":"theme-pack-does-not-have-a-local-file","errorCode":null,"errorMessage":"Theme pack does not have a local file: ","messagePattern":"Theme pack does not have a local file: ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManager.java","lineNumber":543,"sourceCode":"        }\n    }\n\n    /// Removes an installed theme pack from a managed theme-pack directory.\n    ///\n    /// If the removed package is currently selected, the stored theme reference is cleared.\n    ///\n    /// @param themePack the installed theme pack to remove\n    /// @throws IOException if the installed package cannot be removed\n    public static void uninstall(InstalledThemePack themePack) throws IOException {\n        Objects.requireNonNull(themePack);\n\n        if (themePack.builtin()) {\n            throw new IOException(\"Cannot delete a built-in theme pack: \" + themePack.manifest().id());\n        }\n\n        @Nullable Path file = themePack.file();\n        if (file == null) {\n            throw new IOException(\"Theme pack does not have a local file: \" + themePack.manifest().id());\n        }\n\n        Path targetFile = file.toAbsolutePath().normalize();\n        Path localDirectory = THEME_PACKS_DIRECTORY.toAbsolutePath().normalize();\n        Path userDirectory = USER_THEME_PACKS_DIRECTORY.toAbsolutePath().normalize();\n        boolean localThemePack = targetFile.startsWith(localDirectory) && !targetFile.equals(localDirectory);\n        boolean userThemePack = targetFile.startsWith(userDirectory) && !targetFile.equals(userDirectory);\n        if (!localThemePack && !userThemePack) {\n            throw new IOException(\"Theme-pack file is outside the managed directory: \" + targetFile);\n        }\n\n        deleteIfExists(targetFile);\n\n        ThemeReference reference = settings().getSelectedThemeOrDefault();\n        ThemePackManifest manifest = themePack.manifest();\n        if (reference.packId().equals(manifest.id())) {\n            @Nullable InstalledThemePack replacementThemePack = findInstalled(reference);\n            @Nullable Theme replacementTheme = replacementThemePack == null","sourceCodeStart":525,"sourceCodeEnd":561,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/theme/ThemePackManager.java#L525-L561","documentation":"uninstall() throws this IOException when the pack is not built-in but its file() is null, i.e. the InstalledThemePack records a manifest id but no backing local path. Such a pack exists only logically (e.g. an in-memory or resource-only descriptor) and cannot be removed from disk.","triggerScenarios":"Calling uninstall() on a non-builtin InstalledThemePack constructed with a null file path — for example a pack descriptor created without a local install location, or one whose location was cleared.","commonSituations":"Constructing InstalledThemePack records manually with null paths in tests or custom tooling; deserializing pack metadata from config without restoring the file path; a stale cache entry whose file was already deleted and nulled.","solutions":["Verify themePack.file() != null before calling uninstall and treat null-file packs as already removed.","Reinstall the theme pack via ThemePackManager.install(Path) so it has a backing file, then uninstall it.","Prune pack records whose file() is null from your pack registry instead of attempting deletion."],"exampleFix":"// before\nThemePackManager.uninstall(themePack);\n// after\nif (themePack.file() != null) {\n    ThemePackManager.uninstall(themePack);\n}","handlingStrategy":"type-guard","validationCode":"if (pack.builtin()) return;\nif (pack.file() == null) { /* treat as already removed / reinstall first */ }","typeGuard":"static boolean hasLocalFile(InstalledThemePack p) {\n    return !p.builtin() && p.file() != null && Files.isRegularFile(p.file());\n}","tryCatchPattern":"try {\n    ThemePackManager.uninstall(pack);\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Theme pack does not have a local file\")) {\n    // prune the stale record instead of retrying deletion\n    }\n}","preventionTips":["Never construct InstalledThemePack with a null path for uninstall flows","Reinstall via install(Path) if the backing file was lost","Prune pack records with null file() from your registry during startup"],"tags":["theme-pack","uninstall","null-path","state"],"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-16T04:17:20.429Z"}