{"record":{"id":"c3d90ee38418ba94","repo":"elastic/elasticsearch","slug":"invalid-escaped-char-in-s-c3d90e","errorCode":null,"errorMessage":"Invalid escaped char in [{s}]","messagePattern":"Invalid escaped char in \\[(.+?)\\]","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/WordDelimiterTokenFilterFactory.java","lineNumber":155,"sourceCode":"    private static Byte parseType(String s) {\n        if (s.equals(\"LOWER\")) return WordDelimiterFilter.LOWER;\n        else if (s.equals(\"UPPER\")) return WordDelimiterFilter.UPPER;\n        else if (s.equals(\"ALPHA\")) return WordDelimiterFilter.ALPHA;\n        else if (s.equals(\"DIGIT\")) return WordDelimiterFilter.DIGIT;\n        else if (s.equals(\"ALPHANUM\")) return WordDelimiterFilter.ALPHANUM;\n        else if (s.equals(\"SUBWORD_DELIM\")) return WordDelimiterFilter.SUBWORD_DELIM;\n        else return null;\n    }\n\n    private static String parseString(String s) {\n        char[] out = new char[256];\n        int readPos = 0;\n        int len = s.length();\n        int writePos = 0;\n        while (readPos < len) {\n            char c = s.charAt(readPos++);\n            if (c == '\\\\') {\n                if (readPos >= len) throw new RuntimeException(\"Invalid escaped char in [\" + s + \"]\");\n                c = s.charAt(readPos++);\n                switch (c) {\n                    case '\\\\' -> c = '\\\\';\n                    case 'n' -> c = '\\n';\n                    case 't' -> c = '\\t';\n                    case 'r' -> c = '\\r';\n                    case 'b' -> c = '\\b';\n                    case 'f' -> c = '\\f';\n                    case 'u' -> {\n                        if (readPos + 3 >= len) throw new RuntimeException(\"Invalid escaped char in [\" + s + \"]\");\n                        c = (char) Integer.parseInt(s.substring(readPos, readPos + 4), 16);\n                        readPos += 4;\n                    }\n                }\n            }\n            out[writePos++] = c;\n        }\n        return new String(out, 0, writePos);","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/WordDelimiterTokenFilterFactory.java#L137-L173","documentation":"parseString processes backslash escapes inside type_table LHS strings. When a backslash is encountered at the final position (readPos >= len after consuming the '\\'), there is no character left to escape, so it throws RuntimeException. The next char must be one of \\\\, n, t, r, b, f, u; a dangling backslash has no successor at all.","triggerScenarios":"A type_table entry whose LHS ends with a lone backslash: \"\\\\ => ALPHA\" intended as a single backslash but written as a single '\\'; or any LHS containing '\\' not followed by an escape character.","commonSituations":"JSON-level under-escaping: a single backslash in the JSON string becomes a lone backslash in the parsed value; copy-pasting Windows-style paths or regex-style escapes without doubling.","solutions":["Double every literal backslash: write '\\\\\\\\' in JSON for a single '\\\\' character.","Use the appropriate escape sequence (\\\\n, \\\\t, \\\\uXXXX) where you intended a control character.","Validate the JSON-parsed value of each type_table LHS before sending."],"exampleFix":"// before (intended: map backslash to ALPHA; under-escaped)\n\"type_table\": [\"\\ => ALPHA\"]\n// after\n\"type_table\": [\"\\\\ => ALPHA\"]","handlingStrategy":"validation","validationCode":"// A lone trailing backslash (after JSON parsing) will trip the parser\nstatic boolean hasDanglingBackslash(String lhs) {\n  for (int i = 0; i < lhs.length(); i++) {\n    char c = lhs.charAt(i);\n    if (c == '\\\\') {\n      if (i + 1 >= lhs.length()) return true;\n      char n = lhs.charAt(i + 1);\n      if (\"\\\\ntrbfu\".indexOf(n) < 0) return true; // unknown escape also unsafe\n      i++; // consume the escaped char\n    }\n  }\n  return false;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Double every literal backslash in JSON strings.","Validate the JSON-parsed LHS value (not the raw source) before sending."],"tags":["analysis","word-delimiter","type-table","escaping"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}