elastic/elasticsearch · error · IllegalArgumentException

Token filter [{name()}] cannot be used to parse synonyms

Error message

Token filter [{name()}] cannot be used to parse synonyms

What it means

WordDelimiterGraphTokenFilterFactory.getSynonymFilter() is hard-coded to throw IllegalArgumentException. Elasticsearch asks each token filter for a 'synonym filter' (the analyzer used to parse synonym rule text) via TokenFilterFactory.getSynonymFilter(); the word-delimiter-graph filter refuses because its multi-token splitting corrupts the parsing of synonym entries. There is no configuration that enables it.

Source

Thrown at modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/WordDelimiterGraphTokenFilterFactory.java:96

        // If set, causes trailing "'s" to be removed for each subword: "O'Neil's" => "O", "Neil"
        flags |= getFlag(STEM_ENGLISH_POSSESSIVE, settings, "stem_english_possessive", true);
        // If not null is the set of tokens to protect from being delimited
        flags |= getFlag(IGNORE_KEYWORDS, settings, "ignore_keywords", false);
        // If set, suppresses processing terms with KeywordAttribute#isKeyword()=true.
        Set<?> protectedWords = Analysis.getWordSet(env, settings, "protected_words");
        this.protoWords = protectedWords == null ? null : CharArraySet.copy(protectedWords);
        this.flags = flags;
        this.adjustOffsets = settings.getAsBoolean("adjust_offsets", true);
    }

    @Override
    public TokenStream create(TokenStream tokenStream) {
        return new WordDelimiterGraphFilter(tokenStream, adjustOffsets, charTypeTable, flags, protoWords);
    }

    @Override
    public TokenFilterFactory getSynonymFilter() {
        throw new IllegalArgumentException("Token filter [" + name() + "] cannot be used to parse synonyms");
    }

    private static int getFlag(int flag, Settings settings, String key, boolean defaultValue) {
        if (settings.getAsBoolean(key, defaultValue)) {
            return flag;
        }
        return 0;
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. On the synonym/synonym_graph filter, set "analyzer" explicitly to a lightweight analyzer that does NOT contain word_delimiter_graph (e.g. "standard", "whitespace", or a custom chain ending before the delimiter).
  2. Keep the word-delimiter filter only in the search/index analyzers, never in the analyzer used to read synonym rules.
  3. Re-test with _analyze to confirm the synonym-parsing analyzer produces single tokens per rule entry.

Example fix

// before
"my_syn": { "type": "synonym", "synonyms": ["foo,bar"], "analyzer": "my_wdf_analyzer" }
// after
"my_syn": { "type": "synonym", "synonyms": ["foo,bar"], "analyzer": "standard" }
Defensive patterns

Strategy: validation

Validate before calling

// Reject synonym filters that resolve to a word_delimiter_graph analyzer
static String checkSynonymAnalyzer(Map<String,Object> filter, Set<String> wdAnalyzers) {
  if ("synonym".equals(filter.get("type")) || "synonym_graph".equals(filter.get("type"))) {
    Object a = filter.getOrDefault("analyzer", "<default>");
    if (wdAnalyzers.contains(a)) return "analyzer " + a + " contains word_delimiter_graph";
  }
  return null;
}

Prevention

When it happens

Trigger: A synonym/synonym_graph filter that uses an analyzer whose chain resolves to a word_delimiter_graph filter when building the synonym map — either by naming that analyzer explicitly via the 'analyzer' field, or because the index default analyzer contains word_delimiter_graph and no explicit synonym analyzer is set.

Common situations: Building a search analyzer that splits on case/number boundaries and then using the same analyzer (or a parent) to parse synonyms; reusing a custom analyzer for both indexing and synonym parsing.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/794f619c3f660f01. Report an issue: GitHub.