{"record":{"id":"17646146a51ccf83","repo":"HMCL-dev/HMCL","slug":"illegal-pattern-missing-key","errorCode":null,"errorMessage":"Illegal pattern:  Missing Key: ","messagePattern":"Illegal pattern:  Missing Key: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java","lineNumber":263,"sourceCode":"                            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 == '\\'') {\n                    buf.append(key);\n                } else {\n                    if (!tokens.containsKey(key.toString()))\n                        throw new IllegalArgumentException(\"Illegal pattern: \" + value + \" Missing Key: \" + key);\n                    buf.append(tokens.get(key.toString()));\n                }\n            } else {\n                buf.append(c);\n            }\n        }\n        return buf.toString();\n    }\n\n    private <E extends Exception> String parseLiteral(String literal, Map<String, String> var, ExceptionalFunction<String, String, E> plainConverter) throws E {\n        if (StringUtils.isSurrounded(literal, \"{\", \"}\"))\n            return var.get(StringUtils.removeSurrounding(literal, \"{\", \"}\"));\n        else if (StringUtils.isSurrounded(literal, \"'\", \"'\"))\n            return StringUtils.removeSurrounding(literal, \"'\");\n        else if (StringUtils.isSurrounded(literal, \"[\", \"]\"))\n            return gameRepository.getLayout().getArtifactFile(Artifact.fromDescriptor(StringUtils.removeSurrounding(literal, \"[\", \"]\"))).toString();\n        else\n            return plainConverter.apply(replaceTokens(var, literal));","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java#L245-L281","documentation":"When replaceTokens expands a {KEY} token, the key must exist in the vars map built from installer data plus SIDE/MINECRAFT_JAR/MINECRAFT_VERSION/ROOT/INSTALLER/LIBRARY_DIR. If containsKey fails, IllegalArgumentException(\"Illegal pattern: <value> Missing Key: <key>\") is thrown. This indicates the installer references a variable HMCL did not supply.","triggerScenarios":"A processor arg or data literal like \"{LIBRARIES}/{foo}\" where 'foo' is absent from the vars map — typically a Forge installer using a newer data key than the HMCL version supports.","commonSituations":"Installing brand-new Forge releases whose install_profile.json introduces data keys not present in the installed HMCL version; running an outdated launcher against bleeding-edge Forge; forked/patched installers referencing custom variables.","solutions":["Update HMCL to the latest version so new Forge installer variables are supported","Use a Forge version matching what your HMCL release was built for","Inspect install_profile.json and add the missing value via launcher-side customization if you maintain a fork","Report the missing key to HMCL issue tracker if the installer is official"],"exampleFix":"// before (vars lacks key)\nvars.put(\"MINECRAFT_JAR\", ...); // but installer uses {MINECRAFT_LIBRARY}\n// after\nvars.put(\"MINECRAFT_LIBRARY\", FileUtils.getAbsolutePath(libraryDir));","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { installTask.execute(); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"Missing Key:\")) { String key = e.getMessage().substring(e.getMessage().indexOf(\"Missing Key:\") + 12); updateHMCLAndRetry(key.trim()); } else throw e; }","preventionTips":["Keep HMCL at the latest release so new Forge installer variables are recognized","Pair Forge versions with an HMCL version released around the same time","Read the missing key name from the message to identify format drift quickly","Report unknown keys upstream if the installer is official"],"tags":["java","illegalargument","forge-installer","missing-variable"],"backgroundTag":"missing-config-key","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"}