elastic/elasticsearch · error · RuntimeException
Invalid Mapping Rule : [{rule}]. Illegal type.
Error message
Invalid Mapping Rule : [{rule}]. Illegal type. What it means
The right-hand side of a type_table rule must be one of the recognised type identifiers (parseType returns a Byte for known names and null otherwise). When parseType returns null, parseTypes throws RuntimeException. Known names include LOWER, UPPER, ALPHA, DIGIT, SUBWORD_DELIM (and a few others) — anything else is rejected.
Source
Thrown at modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/WordDelimiterTokenFilterFactory.java:122
}
// source => type
private static final Pattern typePattern = Pattern.compile("(.*)\\s*=>\\s*(.*)\\s*$");
/**
* parses a list of MappingCharFilter style rules into a custom byte[] type table
*/
static byte[] parseTypes(Collection<String> rules) {
SortedMap<Character, Byte> typeMap = new TreeMap<>();
for (String rule : rules) {
Matcher m = typePattern.matcher(rule);
if (m.find() == false) {
throw new RuntimeException("Invalid Mapping Rule : [" + rule + "]");
}
String lhs = parseString(m.group(1).trim());
Byte rhs = parseType(m.group(2).trim());
if (lhs.length() != 1) throw new RuntimeException("Invalid Mapping Rule : [" + rule + "]. Only a single character is allowed.");
if (rhs == null) throw new RuntimeException("Invalid Mapping Rule : [" + rule + "]. Illegal type.");
typeMap.put(lhs.charAt(0), rhs);
}
// ensure the table is always at least as big as DEFAULT_WORD_DELIM_TABLE for performance
byte types[] = new byte[Math.max(typeMap.lastKey() + 1, WordDelimiterIterator.DEFAULT_WORD_DELIM_TABLE.length)];
for (int i = 0; i < types.length; i++) {
types[i] = WordDelimiterIterator.getType(i);
}
for (Map.Entry<Character, Byte> mapping : typeMap.entrySet()) {
types[mapping.getKey()] = mapping.getValue();
}
return types;
}
private static Byte parseType(String s) {
if (s.equals("LOWER")) return WordDelimiterFilter.LOWER;
else if (s.equals("UPPER")) return WordDelimiterFilter.UPPER;
else if (s.equals("ALPHA")) return WordDelimiterFilter.ALPHA;View on GitHub (pinned to db6a809a66)
Solutions
- Use one of the recognised type names (LOWER, UPPER, ALPHA, DIGIT, SUBWORD_DELIM) on the RHS.
- Match the casing exactly (these are uppercase constants).
- Re-run the index/template create.
Example fix
// before "type_table": ["- => PUNCT"] // after "type_table": ["- => SUBWORD_DELIM"]
Defensive patterns
Strategy: validation
Validate before calling
static final Set<String> VALID_TYPES = Set.of("LOWER","UPPER","ALPHA","DIGIT","SUBWORD_DELIM");
static List<String> badRhs(List<String> typeTable) {
return typeTable.stream()
.map(r -> r.split("=>", 2)[1].trim())
.filter(rhs -> !VALID_TYPES.contains(rhs))
.toList();
} Prevention
- Cross-check RHS against WordDelimiterFilter type constants (LOWER, UPPER, ALPHA, DIGIT, SUBWORD_DELIM).
- These constants are uppercase; case-sensitive.
When it happens
Trigger: A type_table entry whose RHS is not a valid type constant: "- => PUNCT", "- => lower", "- => DASH".
Common situations: Typo in the type name; using lowercase; inventing a type that does not exist in WordDelimiterFilter.
Related errors
- Invalid Mapping Rule : [{rule}]. Only a single character is
- Invalid Mapping Rule : [{rule}]
- Invalid escaped char in [{s}]
- length parameter must be provided
- Token filter [{name()}] cannot be used to parse synonyms
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/590bad79208bd242.
Report an issue: GitHub.