{"record":{"id":"686f74e6606398d9","repo":"apache/hadoop","slug":"illegal-escaped-string-not-expecting-in-the","errorCode":null,"errorMessage":"Illegal escaped string {}, not expecting {} in the end.","messagePattern":"Illegal escaped string (.+?), not expecting (.+?) in the end\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java","lineNumber":778,"sourceCode":"          throw new IllegalArgumentException(\"Illegal escaped string \" + str + \n              \" unescaped \" + escapeChar + \" at \" + (i-1));\n        } \n        // otherwise discard the escape char\n        result.append(curChar);\n        hasPreEscape = false;\n      } else {\n        if (hasChar(charsToEscape, curChar)) {\n          throw new IllegalArgumentException(\"Illegal escaped string \" + str + \n              \" unescaped \" + curChar + \" at \" + i);\n        } else if (curChar == escapeChar) {\n          hasPreEscape = true;\n        } else {\n          result.append(curChar);\n        }\n      }\n    }\n    if (hasPreEscape ) {\n      throw new IllegalArgumentException(\"Illegal escaped string \" + str + \n          \", not expecting \" + escapeChar + \" in the end.\" );\n    }\n    return result.toString();\n  }\n  \n  /**\n   * Return a message for logging.\n   * @param prefix prefix keyword for the message\n   * @param msg content of the message\n   * @return a message for logging\n   */\n  public static String toStartupShutdownString(String prefix, String[] msg) {\n    StringBuilder b = new StringBuilder(prefix);\n    b.append(\"\\n/************************************************************\");\n    for(String s : msg)\n      b.append(\"\\n\").append(prefix).append(s);\n    b.append(\"\\n************************************************************/\");\n    return b.toString();","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java#L760-L796","documentation":"The final check in StringUtils.unEscapeString: after the scan loop, a still-pending escape (hasPreEscape) means the string ends with a dangling escape character that has nothing to unescape. IllegalArgumentException is thrown — the escape grammar cannot terminate on a bare escape char.","triggerScenarios":"Input like \"value\\\\\" — a trailing backslash produced by truncated user input, shell quoting that eats the escaped char, or code that unconditionally appends the escape char when building lists.","commonSituations":"CLI/shell quoting stripping the character after a backslash; hand-typed config values ending in '\\\\'; join loops that append esc + delimiter but drop the final delimiter.","solutions":["Strip or double a trailing escape char before parsing: if (s.endsWith(\"\\\\\")) s = s.substring(0, s.length()-1) + \"\\\\\\\\\";","Fix the producer that emits the dangling escape (check join/append loops)","Validate input length and last character early and reject with an actionable message","Round-trip test escapeString/unEscapeString on every value you generate"],"exampleFix":"// before\nString raw = \"path=C:\\\\tmp\\\\\";  // trailing dangling escape\nStringUtils.unEscapeString(raw, '\\\\', esc);\n\n// after\nString raw = \"path=C:\\\\tmp\\\\\\\\\"; // trailing backslash itself escaped\nStringUtils.unEscapeString(raw, '\\\\', esc);","handlingStrategy":"validation","validationCode":"if (str != null && !str.isEmpty() && str.charAt(str.length() - 1) == escapeChar) {\n  throw new IllegalArgumentException(\"Value ends with dangling escape char: '\" + str + \"'\");\n}\nString v = StringUtils.unEscapeString(str, escapeChar, charsToEscape);","typeGuard":null,"tryCatchPattern":"try { StringUtils.unEscapeString(str, esc, chars); } catch (IllegalArgumentException e) { /* trailing escape: strip or double it, then retry */ }","preventionTips":["When building delimited strings, append the delimiter after each field rather than the escape after the last one","Validate that user-supplied values do not end with the escape char before saving them","Beware shell/CLI quoting layers that can swallow the character after a backslash, leaving a dangling one"],"tags":["hadoop","stringutils","escaping","configuration","illegalargument"],"backgroundTag":"invalid-escape-sequence","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}