HMCL-dev/HMCL · error · IllegalArgumentException
Illegal pattern (Bad escape)
Error message
Illegal pattern (Bad escape): ${value} What it means
Thrown as IllegalArgumentException from replaceTokens when a literal processor argument ends with a lone backslash ('\\' at the last character position). The escape sequence is incomplete — there is no following character to unescape — so the pattern is rejected.
Solutions
- Fix the offending value in install_profile.json so backslashes are escaped (\\) or no trailing backslash remains
- Regenerate the installer/profile with correct JSON escaping (write paths with \\ or forward slashes)
- Use the official unmodified installer for that NeoForge/Forge version
- If you control the code, strip or normalize trailing backslashes before parseLiteral
Example fix
// before (profile arg) "--target", "C:\\minecraft\\" // after "--target", "C:\\minecraft\\\\"
Defensive patterns
Strategy: validation
Validate before calling
static boolean wellFormedLiteral(String s) {
return s != null && !(s.endsWith("\\"));
} Try / catch
try { task.run(); } catch (IllegalArgumentException e) { if (e.getMessage() != null && e.getMessage().startsWith("Illegal pattern (Bad escape)")) reportProfileLiteralIssue(e.getMessage()); else throw e; } Prevention
- Escape backslashes (\\) in JSON profile values
- Avoid trailing backslashes in Windows paths inside profiles
- Validate profile literals for balanced escapes before install
When it happens
Trigger: parseLiteral falls through to plainConverter.apply(replaceTokens(var, literal)); the value contains '\\' as its final character (x == value.length()-1). Comes from a processor arg or data value in install_profile.json with a trailing backslash (e.g. a Windows path like "C:\\temp\\" written with a single trailing backslash).
Common situations: Hand-edited or generated install_profile.json using raw Windows paths with trailing backslashes; tooling that forgot to escape backslashes (\\) in JSON; copy-pasted values losing an escape character.
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 (Unclosed )
- 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/64ca8e17c2d4ea51.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java:219
String selfVersion,
Path installer) {
this.dependencyManager = dependencyManager;
this.gameRepository = dependencyManager.getGameRepository();
this.manifest = manifest;
this.minecraftJar = minecraftJar;
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;View on GitHub (pinned to 24702dc5a0)