{"record":{"id":"1ec36a9b587f0905","repo":"elastic/elasticsearch","slug":"failed-to-load-keywords-json-from-jsonkeywords","errorCode":null,"errorMessage":"Failed to load keywords JSON from {jsonKeywords} - {message}","messagePattern":"Failed to load keywords JSON from (.+?) - (.+?)","errorType":"exception","errorClass":"GradleException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ValidateJsonNoKeywordsTask.java","lineNumber":227,"sourceCode":"     * multiple languages, so it is easier and more useful to have a single map of keywords.\n     *\n     * @return a mapping from keyword to languages.\n     */\n    private Map<String, Set<String>> loadKeywords(ObjectMapper mapper) {\n        Map<String, Set<String>> languagesByKeyword = new HashMap<>();\n\n        try {\n            final ObjectNode keywordsNode = ((ObjectNode) mapper.readTree(this.jsonKeywords));\n\n            keywordsNode.fieldNames().forEachRemaining(eachLanguage -> {\n                keywordsNode.get(eachLanguage).elements().forEachRemaining(e -> {\n                    final String eachKeyword = e.textValue();\n                    final Set<String> languages = languagesByKeyword.computeIfAbsent(eachKeyword, _keyword -> new HashSet<>());\n                    languages.add(eachLanguage);\n                });\n            });\n        } catch (IOException e) {\n            throw new GradleException(\"Failed to load keywords JSON from \" + jsonKeywords.getName() + \" - \" + e.getMessage(), e);\n        }\n\n        return languagesByKeyword;\n    }\n}\n","sourceCodeStart":209,"sourceCodeEnd":233,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ValidateJsonNoKeywordsTask.java#L209-L233","documentation":"Thrown by ValidateJsonNoKeywordsTask when parsing the keywords JSON file (jsonKeywords) with Jackson raises an IOException. The mapper.readTree call expects a JSON object mapping language -> array of keyword strings; any malformed JSON, I/O error, or unexpected structure surfaces here with the offending file name and parse error message.","triggerScenarios":"The getJsonKeywords() file is opened and parsed into an ObjectNode; a syntax error (trailing comma, unquoted key, truncated file) or a read failure causes Jackson to throw IOException, caught and rethrown as a GradleException naming the file and the parse error.","commonSituations":"Hand-editing the keywords JSON and introducing a syntax error; a merge conflict artifact left inside the file; file truncated by an interrupted write; the file is valid JSON but not a JSON object (e.g. an array), causing the ObjectNode cast downstream to fail (separate failure) — but this specific throw is for parse IOException.","solutions":["Open the named jsonKeywords file and fix the JSON syntax error indicated by the attached IOException message.","Validate the file with a JSON linter (e.g. jq . <file>) before re-running.","If the file was corrupted by a merge conflict, resolve the conflict and re-validate.","Re-run :<project>:validateJsonNoKeywords."],"exampleFix":"// before (invalid JSON)\n{\n  \"en\": [\"select\", \"from\",]\n}\n// after (trailing comma removed)\n{\n  \"en\": [\"select\", \"from\"]\n}","handlingStrategy":"validation","validationCode":"// Validate JSON syntax before the task parses it\ntry (JsonParser p = jsonMapper.getFactory().createParser(jsonKeywordsFile)) {\n    while (p.nextToken() != null) { /* drain */ }\n} catch (IOException e) {\n    throw new IllegalStateException(\"Keywords JSON is malformed: \" + e.getMessage());\n}","typeGuard":null,"tryCatchPattern":"try { Map<String,Set<String>> kw = loadKeywords(jsonKeywordsFile); }\ncatch (GradleException e) { /* message names file + parse error — fix the JSON, don't ignore */ throw e; }","preventionTips":["Lint the keywords JSON (jq . <file>) after every edit.","Resolve git conflicts inside the file fully before running the task.","Avoid hand-editing generated config — regenerate when possible."],"tags":["build","gradle","precommit","json","config"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}