{"record":{"id":"35f1779e3cd40ff0","repo":"HMCL-dev/HMCL","slug":"world-zip-malformed","errorCode":null,"errorMessage":"World zip malformed","messagePattern":"World zip malformed","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java","lineNumber":341,"sourceCode":"            throw new IOException(e);\n        }\n\n        if (Files.isDirectory(worldDir)) {\n            throw new FileAlreadyExistsException(\"World already exists\");\n        }\n\n        if (Files.isRegularFile(file)) {\n            try (FileSystem fs = CompressingUtils.readonly(file).setAutoDetectEncoding(true).build()) {\n                Path levelDatPath = fs.getPath(\"/level.dat\");\n                if (Files.isRegularFile(levelDatPath)) {\n                    fileName = FileUtils.getName(file);\n\n                    new Unzipper(file, worldDir).unzip();\n                } else {\n                    try (Stream<Path> stream = Files.list(fs.getPath(\"/\"))) {\n                        List<Path> subDirs = stream.toList();\n                        if (subDirs.size() != 1) {\n                            throw new IOException(\"World zip malformed\");\n                        }\n                        String subDirectoryName = FileUtils.getName(subDirs.get(0));\n                        new Unzipper(file, worldDir)\n                                .setSubDirectory(\"/\" + subDirectoryName + \"/\")\n                                .unzip();\n                    }\n                }\n\n            }\n            new World(worldDir).rename(name);\n        } else if (Files.isDirectory(file)) {\n            FileUtils.copyDirectory(file, worldDir);\n        }\n    }\n\n    public void export(Path zip, String worldName) throws IOException {\n        if (!Files.isDirectory(file))\n            throw new IOException();","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java#L323-L359","documentation":"World.install throws IOException(\"World zip malformed\") when the zip has no root-level level.dat and its top level does not contain exactly one subdirectory. HMCL needs an unambiguous world root (either level.dat at '/' or a single top-level folder) to know what to extract.","triggerScenarios":"Calling world.install on a zip that lacks /level.dat and whose '/' listing yields 0 or 2+ entries (multiple top-level folders, or loose files plus folders, or an empty zip).","commonSituations":"Zips created by selecting several world folders at once, archives with a README or .DS_Store sitting next to the world folder in the root, archives where the world is nested two levels deep (world/level.dat under an extra folder), or empty zips.","solutions":["Repackage the zip so level.dat is at the root, or so exactly one top-level directory contains it","Remove extraneous root entries (readme files, .DS_Store, extra folders) from the archive","Flatten double-nested archives (zip/world/level.dat -> zip/level.dat)","If several worlds are bundled, split them into one zip per world"],"exampleFix":"// before: zip layout: [WorldA/, WorldB/, readme.txt]\nnew World(Path.of(\"bundle.zip\")).install(savesDir, \"x\"); // malformed\n// after: one zip per world with level.dat at root\n// bundle.zip layout: [level.dat, region/, ...]\nnew World(Path.of(\"worldA.zip\")).install(savesDir, \"WorldA\");","handlingStrategy":"validation","validationCode":"static boolean installableZipLayout(Path zip) throws IOException {\n    try (FileSystem fs = CompressingUtils.readonly(zip).setAutoDetectEncoding(true).build()) {\n        if (Files.isRegularFile(fs.getPath(\"/level.dat\"))) return true;\n        try (Stream<Path> s = Files.list(fs.getPath(\"/\"))) {\n            List<Path> top = s.filter(p -> !p.getFileName().toString().startsWith(\".\")).toList();\n            return top.size() == 1 && Files.isDirectory(top.get(0));\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    world.install(savesDir, name);\n} catch (IOException e) {\n    if (String.valueOf(e.getMessage()).equals(\"World zip malformed\")) {\n        // repackage the zip with level.dat at root or a single top-level folder\n    }\n}","preventionTips":["Create world zips by zipping the world folder's contents, or exactly the folder itself","Exclude stray files (.DS_Store, Thumbs.db, readme.txt) from archive roots","Split multi-world bundles into one archive per world","Avoid double-nesting (zip/world/world/level.dat)"],"tags":["minecraft","zip","world-install","archive"],"backgroundTag":"invalid-argument-format","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"}