{"record":{"id":"3942236e4c0bf5f2","repo":"HMCL-dev/HMCL","slug":"illegal-pattern-bad-escape","errorCode":null,"errorMessage":"Illegal pattern (Bad escape): ","messagePattern":"Illegal pattern \\(Bad escape\\): ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java","lineNumber":235,"sourceCode":"            String selfVersion,\n            Path installer) {\n        this.dependencyManager = dependencyManager;\n        this.gameRepository = dependencyManager.getGameRepository();\n        this.manifest = manifest;\n        this.minecraftJar = minecraftJar;\n        this.installer = installer;\n        this.selfVersion = selfVersion;\n\n        setSignificance(TaskSignificance.MAJOR);\n    }\n\n    private static String replaceTokens(Map<String, String> tokens, String value) {\n        StringBuilder buf = new StringBuilder();\n        for (int x = 0; x < value.length(); x++) {\n            char c = value.charAt(x);\n            if (c == '\\\\') {\n                if (x == value.length() - 1)\n                    throw new IllegalArgumentException(\"Illegal pattern (Bad escape): \" + value);\n                buf.append(value.charAt(++x));\n            } else if (c == '{' || c == '\\'') {\n                StringBuilder key = new StringBuilder();\n                for (int y = x + 1; y <= value.length(); y++) {\n                    if (y == value.length())\n                        throw new IllegalArgumentException(\"Illegal pattern (Unclosed \" + c + \"): \" + value);\n                    char d = value.charAt(y);\n                    if (d == '\\\\') {\n                        if (y == value.length() - 1)\n                            throw new IllegalArgumentException(\"Illegal pattern (Bad escape): \" + value);\n                        key.append(value.charAt(++y));\n                    } else {\n                        if (c == '{' && d == '}') {\n                            x = y;\n                            break;\n                        }\n                        if (c == '\\'' && d == '\\'') {\n                            x = y;","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java#L217-L253","documentation":"replaceTokens scans a literal string from the Forge installer's install_profile.json data/args and interprets backslash as an escape character. If the string ends with a lone backslash there is no following character to escape, so the code throws IllegalArgumentException(\"Illegal pattern (Bad escape): ...\"). This guards against a truncated or hand-mangled pattern in installer metadata.","triggerScenarios":"ForgeNewInstallTask.parseLiteral is called with a literal whose last character is '\\' and which is not fully wrapped in {..} or '..' — i.e. a data/processor-arg value like \"path\\\" ending in a trailing backslash.","commonSituations":"Corrupted or tampered forge installer downloads; manually edited install_profile.json; forge installer formats HMCL doesn't expect (very new/old Forge releases changing data value conventions); non-Windows paths with stray trailing backslashes injected into values.","solutions":["Re-download the Forge installer from the official maven (files.minecraftforge.net) to replace the corrupted/truncated jar","Check the value named in the message in install_profile.json inside the installer jar and fix/remove the trailing backslash","Try a different Forge version (older or newer) whose installer format is known-good","Update HMCL — parsing of installer data has been adjusted across versions"],"exampleFix":"// before (value in install_profile.json)\n{\"MAPPED_JAR\": \"C:\\\\temp\\\\\"}\n// after\n{\"MAPPED_JAR\": \"C:\\\\temp\\\\file.txt\"}","handlingStrategy":"validation","validationCode":"// before installing, sanity-check installer data values\ntry (var zip = new java.util.zip.ZipFile(installer.toFile())) {\n    String json = new String(zip.getInputStream(zip.getEntry(\"install_profile.json\")).readAllBytes());\n    if (json.matches(\".*[^\\\\\\\\]\\\\\\\\\\\\\"\\\\s*,\\\\s*\")) throw new IllegalStateException(\"value ends with bare backslash\");\n}","typeGuard":null,"tryCatchPattern":"try { installTask.execute(); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Illegal pattern\")) { reDownloadInstaller(); } else throw e; }","preventionTips":["Only download installers from official Forge maven endpoints","Never hand-edit install_profile.json inside the installer jar","Keep HMCL updated for new installer format support","Check file size/hash against the maven metadata before installing"],"tags":["java","illegalargument","forge-installer","string-parsing"],"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-15T23:17:13.987Z"}