{"record":{"id":"daa25753d2bbc3ed","repo":"languagetool-org/languagetool","slug":"missing-text-or-data-parameter","errorCode":null,"errorMessage":"Missing 'text' or 'data' parameter","messagePattern":"Missing 'text' or 'data' parameter","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"languagetool-server/src/main/java/org/languagetool/server/ApiV2.java","lineNumber":169,"sourceCode":"    } else if (parameters.containsKey(\"data\")) {\n      ObjectMapper mapper = new ObjectMapper();\n      JsonNode data;\n      try {\n        data = mapper.readTree(parameters.get(\"data\"));\n      } catch (JsonProcessingException e) {\n        throw new BadRequestException(\"Could not parse JSON from 'data' parameter\", e);\n      }\n      if (data.get(\"text\") != null && data.get(\"annotation\") != null) {\n        throw new BadRequestException(\"'data' key in JSON requires either 'text' or 'annotation' key, not both\");\n      } else if (data.get(\"text\") != null) {\n        aText = getAnnotatedTextFromString(data, data.get(\"text\").asText());\n      } else if (data.get(\"annotation\") != null) {\n        aText = getAnnotatedTextFromJson(data);\n      } else {\n        throw new BadRequestException(\"'data' key in JSON requires 'text' or 'annotation' key\");\n      }\n    } else {\n      throw new BadRequestException(\"Missing 'text' or 'data' parameter\");\n    }\n    //get from config\n    if (config.logIp && aText.getPlainText().trim().equals(config.logIpMatchingPattern)) {\n      handleIpLogMatch(httpExchange, remoteAddress, parameters);\n      //no need to check text again rules\n      return;\n    }\n    textChecker.checkText(aText, httpExchange, parameters, errorRequestLimiter, remoteAddress);\n  }\n\n  private void handleIpLogMatch(HttpExchange httpExchange, String remoteAddress, Map<String, String> parameters) {\n    Logger logger = LoggerFactory.getLogger(ApiV2.class);\n    InetSocketAddress localAddress = httpExchange.getLocalAddress();\n    logger.info(String.format(\"Found log-my-IP text in request from: %s to: %s, requestParams: %s\", remoteAddress, localAddress.toString(), parameters));\n  }\n\n  private void handleWordsRequest(HttpExchange httpExchange, Map<String, String> params, HTTPServerConfig config) throws Exception {\n    ensureGetMethod(httpExchange, \"/words\");","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-server/src/main/java/org/languagetool/server/ApiV2.java#L151-L187","documentation":"handleCheckRequest in ApiV2 requires the check request to carry the text to proofread. It accepts either a 'text' parameter (plain text) or a 'data' parameter containing JSON with 'text' or 'annotation'. If neither is supplied (or 'data' holds neither key), the server rejects the request with a BadRequestException so it never runs the grammar check.","triggerScenarios":"POST /v2/check with no 'text' field; POST with 'data' whose JSON object contains neither 'text' nor 'annotation'; clients sending the payload under a misspelled key like 'txt' or 'content'.","commonSituations":"Clients switching from form-encoded 'text' to the annotated 'data' JSON format but forgetting the inner 'text' key; automated scripts that drop the body entirely; proxies or HTTP libraries silently discarding multipart/form-data bodies.","solutions":["Add 'text=<your text>' to the request body (form field, not query string, for POST).","If using 'data', wrap the payload as JSON with a 'text' key: data={\"text\":\"Hello\"} or an 'annotation' array.","Check that your HTTP client actually sends the request body and that the Content-Type matches the encoding you use.","Verify the parameter names are exactly 'text', 'data', or 'annotation' — case-sensitive."],"exampleFix":"// before\ncurl -X POST https://api.languagetool.org/v2/check -d 'language=en-US'\n// after\ncurl -X POST https://api.languagetool.org/v2/check -d 'language=en-US' --data-urlencode 'text=This is a test.'","handlingStrategy":"validation","validationCode":"if (body.text == null && body.data == null) throw new Error('v2/check requires \"text\" or \"data\"');\nif (body.data != null) {\n  const d = typeof body.data === 'string' ? JSON.parse(body.data) : body.data;\n  if (d.text == null && d.annotation == null) throw new Error('\"data\" requires \"text\" or \"annotation\"');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include either a 'text' form field or a JSON 'data' payload in /v2/check requests.","Verify the HTTP client sends the body for POST and uses the right Content-Type.","Keep parameter names exact: 'text', 'data', 'annotation'."],"tags":["http","rest-api","validation","languagetool"],"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"}