{"record":{"id":"88daf437321d4091","repo":"languagetool-org/languagetool","slug":"json-item-elem-doesn-t-contain-required-propert","errorCode":null,"errorMessage":"JSON item ${elem} doesn't contain required property '${propertyName}'","messagePattern":"JSON item (.+?) doesn't contain required property '(.+?)'","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-http-client/src/main/java/org/languagetool/remote/RemoteLanguageTool.java","lineNumber":334,"sourceCode":"    remoteMatch.setLocQualityIssueType(getOrNull(rule, \"issueType\"));\n    List<String> urls = getValueList(rule, \"urls\");\n    if (urls.size() > 0) {\n      remoteMatch.setUrl(urls.get(0));\n    }\n    Map<String, Object> category = (Map<String, Object>) rule.get(\"category\");\n    remoteMatch.setCategory(getOrNull(category, \"name\"));\n    remoteMatch.setCategoryId(getOrNull(category, \"id\"));\n\n    remoteMatch.setReplacements(getValueList(match, \"replacements\"));\n    return remoteMatch;\n  }\n\n  private Object getRequired(Map<String, Object> elem, String propertyName) {\n    Object val = elem.get(propertyName);\n    if (val != null) {\n      return val;\n    }\n    throw new RuntimeException(\"JSON item \" + elem + \" doesn't contain required property '\" + propertyName + \"'\");\n  }\n\n  private String getRequiredString(Map<String, Object> elem, String propertyName) {\n    return (String) getRequired(elem, propertyName);\n  }\n\n  private String getOrNull(Map<String, Object> elem, String propertyName) {\n    Object val = elem.get(propertyName);\n    if (val != null) {\n      return (String) val;\n    }\n    return null;\n  }\n\n  private List<String> getValueList(Map<String, Object> match, String propertyName) {\n    List<Object> matches = (List<Object>) match.get(propertyName);\n    List<String> l = new ArrayList<>();\n    if (matches != null) {","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-http-client/src/main/java/org/languagetool/remote/RemoteLanguageTool.java#L316-L352","documentation":"RemoteLanguageTool.getRequired extracts a mandatory property from a JSON response item and throws a RuntimeException when the key is absent (null). It is the client's contract check that the server response contains every field the Java model requires; callers include offset(), errorLength(), contextOffset() and getRequiredString().","triggerScenarios":"Parsing a LanguageTool server response JSON whose matches/objects lack required keys — e.g. a proxy or different server version returning a modified schema, an error JSON being parsed as a success payload, or a truncated response.","commonSituations":"Running a newer client against an older server (or vice versa) where response fields changed; middleboxes stripping/renaming fields; pointing the client at a non-LanguageTool endpoint that returns valid but unrelated JSON.","solutions":["Log the raw JSON response and compare it with the expected /v2/check schema (offset, length, context, etc.)","Align client and server versions of LanguageTool","Check the URL actually points at a LanguageTool API endpoint, not a login/error page returning JSON","If a field is legitimately optional in your setup, adjust the client model or add a default"],"exampleFix":"// before\nString base = getRequiredString(map, \"context\"); // throws if absent\n// after\nif (map.containsKey(\"context\")) {\n  String base = getRequiredString(map, \"context\");\n} else {\n  log.warn(\"missing 'context' in response item: \" + map);\n}","handlingStrategy":"validation","validationCode":"Map<String, Object> match = ...; // parsed JSON item\nfor (String req : List.of(\"offset\", \"length\", \"context\", \"message\")) {\n  if (!match.containsKey(req)) throw new IllegalStateException(\"missing field: \" + req);\n}","typeGuard":"static boolean hasRequiredFields(Map<String, Object> item, String... keys) {\n  return Arrays.stream(keys).allMatch(item::containsKey);\n}","tryCatchPattern":"try {\n  CheckResult r = lt.check(text);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"doesn't contain required property\")) {\n    log.error(\"unexpected server response schema: \" + e.getMessage());\n  } else throw e;\n}","preventionTips":["Keep client and server LanguageTool versions aligned","Capture the raw HTTP body on failure for diagnosis","Point the client only at genuine /v2 LanguageTool endpoints"],"tags":["java","json","api-client"],"backgroundTag":"missing-required-argument","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}