{"record":{"id":"291c8453add45e5e","repo":"elastic/elasticsearch","slug":"deprecated-fields-not-supported-in-parsername","errorCode":null,"errorMessage":"deprecated fields not supported in [{parserName}] but got [{oldName}] at [{location}] which is a deprecated name for [{replacedName}]","messagePattern":"deprecated fields not supported in \\[(.+?)\\] but got \\[(.+?)\\] at \\[(.+?)\\] which is a deprecated name for \\[(.+?)\\]","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"libs/x-content/src/main/java/org/elasticsearch/xcontent/DeprecationHandler.java","lineNumber":29,"sourceCode":"\nimport java.util.function.Supplier;\n\n/**\n * Callback for notifying the creator of the {@link XContentParser} that\n * parsing hit a deprecated field.\n */\npublic interface DeprecationHandler {\n    /**\n     * Throws an {@link UnsupportedOperationException} when parsing hits a\n     * deprecated field. Use this when creating an {@link XContentParser}\n     * that won't interact with deprecation logic at all or when you want\n     * to fail fast when parsing deprecated fields.\n     */\n    DeprecationHandler THROW_UNSUPPORTED_OPERATION = new DeprecationHandler() {\n        @Override\n        public void logReplacedField(String parserName, Supplier<XContentLocation> location, String oldName, String replacedName) {\n            if (parserName != null) {\n                throw new UnsupportedOperationException(\n                    \"deprecated fields not supported in [\"\n                        + parserName\n                        + \"] but got [\"\n                        + oldName\n                        + \"] at [\"\n                        + location.get()\n                        + \"] which is a deprecated name for [\"\n                        + replacedName\n                        + \"]\"\n                );\n            } else {\n                throw new UnsupportedOperationException(\n                    \"deprecated fields not supported here but got [\" + oldName + \"] which is a deprecated name for [\" + replacedName + \"]\"\n                );\n            }\n        }\n\n        @Override","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/x-content/src/main/java/org/elasticsearch/xcontent/DeprecationHandler.java#L11-L47","documentation":"The THROW_UNSUPPORTED_OPERATION DeprecationHandler.logReplacedField throws UnsupportedOperationException when the parser encounters a field supplied under a deprecated 'replaced' name (the field is deprecated in favor of a different field) and parserName is non-null. parserName identifies which parser's context rejected it; location pins the source position. Use this handler to fail fast on deprecated fields in strict contexts.","triggerScenarios":"Parsing input with DeprecationHandler.THROW_UNSUPPORTED_OPERATION where the JSON contains a field name registered as a deprecated alias that maps to a replacement field, and the parser was created with a non-null parserName. Common in internal/strict parsing paths that must reject legacy field names.","commonSituations":"Tightening a REST endpoint to reject pre-deprecation request shapes. Internal plugin parsing that must not accept legacy aliases. Test harnesses asserting no deprecated fields leak through.","solutions":["Rename the deprecated field in the input to its replacement (replacedName in the message).","If legacy names must be tolerated, create the parser with a lenient DeprecationHandler (IGNORE_DEPRECATIONS or one that logs) instead of THROW_UNSUPPORTED_OPERATION.","Update the ParseField registration if the alias should no longer be considered deprecated."],"exampleFix":"// before (input)\n{\"boost\": 2.0}   // 'boost' is a deprecated alias\n// with THROW_UNSUPPORTED_OPERATION handler -> error\n\n// after\n{\"boost_value\": 2.0}   // use the replacement name","handlingStrategy":"validation","validationCode":"// strip or rename deprecated 'replaced' aliases before strict parsing\nMap<String,Object> body = parseToMap(parserClone);\nMap<String,String> replaced = Map.of(\"boost\", \"boost_value\");\nreplaced.forEach((old, neu) -> { if (body.containsKey(old)) { body.put(neu, body.remove(old)); } });\n// re-serialize and parse with THROW_UNSUPPORTED_OPERATION","typeGuard":null,"tryCatchPattern":"try {\n    p.parse(parser, ctx);\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().contains(\"deprecated name for [\")) {\n        // extract replacement name and retry, or downgrade to a logging handler\n    }\n}","preventionTips":["Maintain a deprecated-alias -> replacement map at the controller and normalize input before strict parsing.","Only use THROW_UNSUPPORTED_OPERATION where legacy names must be hard-rejected; prefer logging handlers during migration windows.","Communicate field renames in release notes and SDK updates so clients stop sending old names."],"tags":["xcontent","deprecation","strict","field-alias"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}