apache/hadoop · error · IllegalArgumentException

Illegal escaped string {} unescaped {} at {}

Error message

Illegal escaped string {} unescaped {} at {}

What it means

StringUtils.unEscapeString(str, escapeChar, charsToEscape) processes escape sequences in delimited strings (the standard way Hadoop escapes ',', '=', '\' in Configuration values). It throws IllegalArgumentException when a character follows the escape char but is neither the escape char itself nor in charsToEscape — an escape that unescapes nothing meaningful.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java:760

   * unEscapeString.
   * @param str str.
   * @param escapeChar escapeChar.
   * @param charsToEscape array of characters to unescape
   * @return escape string.
   */
  public static String unEscapeString(String str, char escapeChar, 
                                      char[] charsToEscape) {
    if (str == null) {
      return null;
    }
    StringBuilder result = new StringBuilder(str.length());
    boolean hasPreEscape = false;
    for (int i=0; i<str.length(); i++) {
      char curChar = str.charAt(i);
      if (hasPreEscape) {
        if (curChar != escapeChar && !hasChar(charsToEscape, curChar)) {
          // no special char
          throw new IllegalArgumentException("Illegal escaped string " + str + 
              " unescaped " + escapeChar + " at " + (i-1));
        } 
        // otherwise discard the escape char
        result.append(curChar);
        hasPreEscape = false;
      } else {
        if (hasChar(charsToEscape, curChar)) {
          throw new IllegalArgumentException("Illegal escaped string " + str + 
              " unescaped " + curChar + " at " + i);
        } else if (curChar == escapeChar) {
          hasPreEscape = true;
        } else {
          result.append(curChar);
        }
      }
    }
    if (hasPreEscape ) {
      throw new IllegalArgumentException("Illegal escaped string " + str + 

View on GitHub (pinned to 2add963021)

Solutions

  1. Escape every literal escape char in the input (double backslashes on Windows paths: C:\\tmp)
  2. Produce values with StringUtils.escapeString(value, escapeChar, sameCharsToEscape) so both sides agree on the format
  3. Validate/normalize input before unescaping and reject unknown escape sequences with a clear message
  4. If a trailing sequence keeps failing, prefer comma-separated values parsed with StringSplitter-style APIs that document their escaping

Example fix

// before
String raw = "C:\tmp\\x"; // single backslash: '\t' seen as escaping ordinary 't'
String v = StringUtils.unEscapeString(raw, '\\', new char[]{',', '='});

// after
String raw = "C:\\tmp\\x"; // every literal backslash doubled
String v = StringUtils.unEscapeString(raw, '\\', new char[]{',', '='});
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidEscaped(String s, char esc, char[] toEscape) {
  String specials = new String(toEscape);
  for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
    if (c == esc) {
      if (i + 1 >= s.length()) return false;               // dangling escape
      char n = s.charAt(++i);
      if (n != esc && specials.indexOf(n) < 0) return false; // escape of ordinary char
    } else if (specials.indexOf(c) >= 0) {
      return false;                                         // raw special char
    }
  }
  return true;
}
// use: isValidEscaped(value, '\\', new char[]{',', '='}) before unEscapeString

Try / catch

try { StringUtils.unEscapeString(str, esc, chars); } catch (IllegalArgumentException e) { /* message prints str, offending char and index — fix escaping at the producer */ }

Prevention

When it happens

Trigger: Parsing configuration values where an input like 'a\\z' uses the escape char ('\\') before an ordinary character: Windows paths 'C:\\tmp' passed with single backslashes, or values escaped by different rules than the parser expects.

Common situations: User-supplied config values with stray backslashes; producers that escape a different char set than the consumer's charsToEscape; hand-edited XML values with half-escaped delimiters.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/4714a7451140b7f7. Report an issue: GitHub.