{"record":{"id":"23eac13167c97b80","repo":"elastic/elasticsearch","slug":"synonym-requires-either-synonyms-synonyms-set","errorCode":null,"errorMessage":"synonym requires either `synonyms`, `synonyms_set` or `synonyms_path` to be configured","messagePattern":"synonym requires either `synonyms`, `synonyms_set` or `synonyms_path` to be configured","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/SynonymTokenFilterFactory.java","lineNumber":160,"sourceCode":"            this.settingName = settingName;\n        }\n\n        public abstract ReaderWithOrigin getRulesReader(SynonymTokenFilterFactory factory, IndexCreationContext context);\n\n        public String getSettingName() {\n            return settingName;\n        }\n\n        public static SynonymsSource fromSettings(Settings settings) {\n            SynonymsSource synonymsSource;\n            if (settings.hasValue(SynonymsSource.INLINE.getSettingName())) {\n                synonymsSource = SynonymsSource.INLINE;\n            } else if (settings.hasValue(SynonymsSource.INDEX.getSettingName())) {\n                synonymsSource = SynonymsSource.INDEX;\n            } else if (settings.hasValue(SynonymsSource.LOCAL_FILE.getSettingName())) {\n                synonymsSource = SynonymsSource.LOCAL_FILE;\n            } else {\n                throw new IllegalArgumentException(\n                    \"synonym requires either `\"\n                        + SynonymsSource.INLINE.getSettingName()\n                        + \"`, `\"\n                        + SynonymsSource.INDEX.getSettingName()\n                        + \"` or `\"\n                        + SynonymsSource.LOCAL_FILE.getSettingName()\n                        + \"` to be configured\"\n                );\n            }\n\n            return synonymsSource;\n        }\n    }\n\n    private final String format;\n    private final boolean expand;\n    private final boolean lenient;\n    protected final Settings settings;","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/SynonymTokenFilterFactory.java#L142-L178","documentation":"The synonym / synonym_graph token filter needs exactly one source of synonym rules. SynonymTokenFilterFactory.SynonymsSource.fromSettings walks three mutually-exclusive keys in priority order — INLINE ('synonyms'), INDEX ('synonyms_set'), LOCAL_FILE ('synonyms_path') — and throws when none of the three is present in the filter's Settings. The check is a simple hasValue() probe per key, so an empty value still counts as 'present' and will fail later at parse time rather than here.","triggerScenarios":"Creating or updating an index whose analyzer defines a filter of type 'synonym' or 'synonym_graph' without any of: 'synonyms', 'synonyms_set', 'synonyms_path'. Also triggered via the _analyze API with such a filter, or via an index template whose settings omit all three keys.","commonSituations":"Migrating an older analyzer config and dropping the source key; typo'ing the key (e.g. 'synonym' singular, 'synonym_path'); placing the key at the wrong nesting level (under the analyzer instead of under the filter); copying a synonym_set definition but forgetting to also reference it by name.","solutions":["Add exactly one of: \"synonyms\": [\"a,b\"], \"synonyms_set\": \"my-set\", or \"synonyms_path\": \"analysis/synonyms.txt\" to the filter's settings.","Verify the key spelling matches one of the three exact names (synonyms / synonyms_set / synonyms_path).","Confirm the key lives inside the filter object, not at analyzer or index-settings level.","For synonyms_set, ensure the synonyms set was previously created via PUT _synonyms and is referenced by its name."],"exampleFix":"// before\n{\n  \"settings\": {\n    \"analysis\": {\n      \"filter\": { \"my_syn\": { \"type\": \"synonym\" } }\n    }\n  }\n}\n// after\n{\n  \"settings\": {\n    \"analysis\": {\n      \"filter\": {\n        \"my_syn\": {\n          \"type\": \"synonym\",\n          \"synonyms\": [\"car,automobile\", \"socks,sock\"]\n        }\n      }\n    }\n  }\n}","handlingStrategy":"validation","validationCode":"// Pre-flight before creating an index with a synonym filter\nFunction<Map<String,Object>, String> checkSynSource = filter -> {\n  boolean hasInline  = filter.containsKey(\"synonyms\");\n  boolean hasIndex   = filter.containsKey(\"synonyms_set\");\n  boolean hasPath    = filter.containsKey(\"synonyms_path\");\n  int n = (hasInline?1:0) + (hasIndex?1:0) + (hasPath?1:0);\n  if (n == 0) return \"missing: add one of synonyms | synonyms_set | synonyms_path\";\n  if (n > 1) return \"ambiguous: pick exactly one source\";\n  return null; // ok\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat the synonym source keys as required in any analyzer template that includes a synonym filter.","Run a dry-run _analyze against a new analyzer before applying it to a production index.","Lint index templates in CI for the presence of a source key on every synonym/synonym_graph filter."],"tags":["analysis","synonyms","configuration","index-creation"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}