{"record":{"id":"03367714ba514ce5","repo":"HMCL-dev/HMCL","slug":"illegal-pattern-unclosed-char-value","errorCode":null,"errorMessage":"Illegal pattern (Unclosed ${char}): ${value}","messagePattern":"Illegal pattern \\(Unclosed (.+?)\\): (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java","lineNumber":225,"sourceCode":"        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;\n                            break;\n                        }\n                        key.append(d);\n                    }\n                }\n                if (c == '\\'') {","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java#L207-L243","documentation":"Thrown as IllegalArgumentException from replaceTokens when a '{' or '\\'' starts a token/quoted section that is never closed before the end of the string: the scanning inner loop reaches the end of the value without finding the matching '}' or '\\''. The literal is structurally invalid.","triggerScenarios":"A processor arg or data value contains '{' without a matching '}' (e.g. \"{MINECRAFT_JAR\" ) or an odd number of quote characters (\"'literal\" ), so the inner loop hits y == value.length() during parseLiteral of install_profile.json content.","commonSituations":"Hand-edited or malformed install_profile.json processor args; a placeholder whose closing brace was lost in editing or JSON escaping; template values pasted partially.","solutions":["Correct the literal in install_profile.json so every '{' has a matching '}' and quotes are paired","Regenerate the installer profile or use the official installer jar","Validate the JSON content of install_profile.json inside the installer","If you control the code, pre-validate balanced braces/quotes before calling parseLiteral"],"exampleFix":"// before\n\"{MINECRAFT_JAR\"\n// after\n\"{MINECRAFT_JAR}\"","handlingStrategy":"validation","validationCode":"static boolean balanced(String s) {\n    int braces = 0, quotes = 0;\n    for (int i = 0; i < s.length(); i++) {\n        char c = s.charAt(i);\n        if (c == '\\\\') i++;\n        else if (c == '{') braces++;\n        else if (c == '}') braces--;\n        else if (c == '\\'') quotes++;\n    }\n    return braces == 0 && quotes % 2 == 0;\n}","typeGuard":null,"tryCatchPattern":"try { task.run(); } catch (IllegalArgumentException e) { if (e.getMessage() != null && e.getMessage().contains(\"Illegal pattern (Unclosed\")) reportUnclosedToken(e.getMessage()); else throw e; }","preventionTips":["Check every '{' has a matching '}' and quotes are paired in profile args","Regenerate install_profile.json programmatically rather than hand-editing","Validate JSON/template literals before shipping an installer"],"tags":["parsing","unclosed-token","install-profile","argument"],"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-23T08:17:48.524Z"}