HMCL-dev/HMCL · error · IllegalArgumentException
Illegal pattern (Unclosed )
Error message
Illegal pattern (Unclosed ${char}): ${value} What it means
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.
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
Example fix
// before
"{MINECRAFT_JAR"
// after
"{MINECRAFT_JAR}" Defensive patterns
Strategy: validation
Validate before calling
static boolean balanced(String s) {
int braces = 0, quotes = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\\') i++;
else if (c == '{') braces++;
else if (c == '}') braces--;
else if (c == '\'') quotes++;
}
return braces == 0 && quotes % 2 == 0;
} Try / catch
try { task.run(); } catch (IllegalArgumentException e) { if (e.getMessage() != null && e.getMessage().contains("Illegal pattern (Unclosed")) reportUnclosedToken(e.getMessage()); else throw e; } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Illegal pattern (Bad escape)
- Illegal pattern: Missing Key
- Artifact name is malformed
- Bad Build-Number
- Expected typed ID prefix '" + expectedPrefix + "'
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/03367714ba514ce5.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java:225
this.installer = installer;
this.selfVersion = selfVersion;
setSignificance(TaskSignificance.MAJOR);
}
private static String replaceTokens(Map<String, String> tokens, String value) {
StringBuilder buf = new StringBuilder();
for (int x = 0; x < value.length(); x++) {
char c = value.charAt(x);
if (c == '\\') {
if (x == value.length() - 1)
throw new IllegalArgumentException("Illegal pattern (Bad escape): " + value);
buf.append(value.charAt(++x));
} else if (c == '{' || c == '\'') {
StringBuilder key = new StringBuilder();
for (int y = x + 1; y <= value.length(); y++) {
if (y == value.length())
throw new IllegalArgumentException("Illegal pattern (Unclosed " + c + "): " + value);
char d = value.charAt(y);
if (d == '\\') {
if (y == value.length() - 1)
throw new IllegalArgumentException("Illegal pattern (Bad escape): " + value);
key.append(value.charAt(++y));
} else {
if (c == '{' && d == '}') {
x = y;
break;
}
if (c == '\'' && d == '\'') {
x = y;
break;
}
key.append(d);
}
}
if (c == '\'') {View on GitHub (pinned to 24702dc5a0)