{"record":{"id":"67052d2a2ec26fbb","repo":"HMCL-dev/HMCL","slug":"illegal-pattern-value-missing-key-key","errorCode":null,"errorMessage":"Illegal pattern: ${value} Missing Key: ${key}","messagePattern":"Illegal pattern: (.+?) Missing Key: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java","lineNumber":247,"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":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java#L229-L265","documentation":"Thrown as IllegalArgumentException from replaceTokens when a '{Key}' placeholder refers to a variable not present in the tokens (vars) map. The processor profile references data (e.g. a substitution variable) that this install task never populated, so token substitution cannot proceed.","triggerScenarios":"A plain (non fully-bracketed/quoted) processor arg contains {Key} where tokens.containsKey(key) is false — the key is neither in profile.getData()-derived vars nor the injected SIDE/MINECRAFT_JAR/MINECRAFT_VERSION/ROOT/INSTALLER/LIBRARY_DIR entries.","commonSituations":"Unsupported or modified install_profile.json introducing new placeholders; launcher not supplying a variable expected by a newer Forge/NeoForge processor format; typo in the variable name in a hand-built profile.","solutions":["Use the official installer for the target NeoForge/Forge version so placeholder names match what the launcher supplies","Compare the missing key from the error message against vars populated in NeoForgeOldInstallTask.execute (SIDE, MINECRAFT_JAR, MINECRAFT_VERSION, ROOT, INSTALLER, LIBRARY_DIR, plus profile data)","Update HMCL — newer profiles may need newer launcher support","Report the version to HMCL if the official profile still references an unsupported key"],"exampleFix":"// before (profile references undefined key)\n{CUSTOM_PATCH}\n// after (defined key)\n{MINECRAFT_JAR}","handlingStrategy":"validation","validationCode":"// verify all placeholders resolve before running processors\njava.util.regex.Matcher m = java.util.regex.Pattern.compile(\"\\\\{([^}]+)\\\\}\").matcher(arg);\nwhile (m.find()) if (!vars.containsKey(m.group(1))) throw new IllegalStateException(\"Missing var: \" + m.group(1));","typeGuard":null,"tryCatchPattern":"try { task.run(); } catch (IllegalArgumentException e) { if (e.getMessage() != null && e.getMessage().startsWith(\"Illegal pattern:\")) reportMissingVar(e.getMessage()); else throw e; }","preventionTips":["Keep HMCL updated so newly introduced profile variables are supported","Only use official installer jars whose placeholders match launcher-supplied vars","Diff custom profiles against the official one to catch unknown placeholders"],"tags":["parsing","placeholder","missing-variable","install-profile"],"backgroundTag":"missing-required-config-field","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"}