{"record":{"id":"e0167c06906c14fb","repo":"languagetool-org/languagetool","slug":"missing-text-or-data-parameter-e0167c","errorCode":null,"errorMessage":"Missing 'text' or 'data' parameter","messagePattern":"Missing 'text' or 'data' parameter","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"languagetool-server/src/main/java/org/languagetool/server/TextChecker.java","lineNumber":886,"sourceCode":"  }\n\n  private List<String> getUserDictWords(UserLimits limits, List<String> groups) {\n    DatabaseAccess db = DatabaseAccess.getInstance();\n    return db.getWords(limits, groups, RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT);\n  }\n\n  private List<Rule> getUserRules(UserLimits limits, Language lang, List<String> groups) {\n    if (limits.getPremiumUid() != null && DatabaseAccess.isReady()) {\n      DatabaseAccess db = DatabaseAccess.getInstance();\n      return db.getRules(limits, lang, groups);\n    } else {\n      return Collections.emptyList();\n    }\n  }\n\n  protected void checkParams(Map<String, String> parameters) {\n    if (parameters.get(\"text\") == null && parameters.get(\"data\") == null) {\n      throw new BadRequestException(\"Missing 'text' or 'data' parameter\");\n    }\n  }\n\n  private List<CheckResults> getRuleMatches(AnnotatedText aText, Language lang,\n                                         Language motherTongue, Map<String, String> parameters,\n                                         QueryParams params, UserConfig userConfig,\n                                         /*DetectedLanguage detLang,\n                                         List<String> preferredLangs, List<String> preferredVariants,*/\n                                         RuleMatchListener listener) throws Exception {\n    if (cache != null && cache.requestCount() > 0 && cache.requestCount() % CACHE_STATS_PRINT == 0) {\n      String sentenceHitPercentage = String.format(Locale.ENGLISH, \"%.2f\", cache.getSentenceCache().stats().hitRate() * 100.0f);\n      String matchesHitPercentage = String.format(Locale.ENGLISH, \"%.2f\", cache.getMatchesCache().stats().hitRate() * 100.0f);\n      String remoteHitPercentage = String.format(Locale.ENGLISH, \"%.2f\", cache.getRemoteMatchesCache().stats().hitRate() * 100.0f);\n      log.info(\"Cache stats: \" + sentenceHitPercentage + \"% / \" + matchesHitPercentage + \"% / \" + remoteHitPercentage + \"% hit rate\");\n    }\n\n    if (parameters.get(\"sourceText\") != null) {\n      if (parameters.get(\"sourceLanguage\") == null) {","sourceCodeStart":868,"sourceCodeEnd":904,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-server/src/main/java/org/languagetool/server/TextChecker.java#L868-L904","documentation":"A check request must carry the text either as the 'text' parameter (plain text) or as 'data' (annotated JSON text). checkParams throws BadRequestException when both are absent, since there is nothing to check.","triggerScenarios":"POSTing /v2/check without a text or data field — e.g. only language=... and options, an empty body, a misnamed field (txt=, content=), or multipart/JSON bodies whose fields are not parsed into the params map.","commonSituations":"Hand-rolled curl calls missing -d text=..., form encoding mistakes, clients sending JSON bodies to an endpoint that expects form-encoded parameters, or a parameter name typo after refactoring.","solutions":["Add the text parameter: text=Your+text+to+check","Or supply the annotated-text JSON via the data parameter for advanced markup","Verify the request uses application/x-www-form-urlencoded fields the server actually parses (check client serialization)","Log the outgoing params before the call to confirm 'text'/'data' keys are present"],"exampleFix":"// before\ncurl -d language=en-US http://server/v2/check\n// after\ncurl -d text=Hello+world -d language=en-US http://server/v2/check","handlingStrategy":"validation","validationCode":"function buildCheckParams(text, options = {}) {\n  if (text == null && options.data == null) {\n    throw new Error(\"Provide either 'text' or 'data' before calling /v2/check\");\n  }\n  return { text, ...options };\n}","typeGuard":"function hasCheckPayload(p) {\n  return p != null && (typeof p.text === 'string' ? p.text.length > 0 : p.data != null);\n}","tryCatchPattern":"try {\n  return await api.check(params);\n} catch (e) {\n  if (e.status === 400 && /Missing 'text' or 'data'/.test(e.message)) {\n    throw new Error('Request payload was empty; check client serialization (form-encoding vs JSON)');\n  }\n  throw e;\n}","preventionTips":["Assert text/data presence in the client's request builder","Verify the Content-Type matches what the server parses (form-encoded, not raw JSON)","Watch for renamed/mistyped parameter keys after refactors","Log outgoing bodies in debug mode during integration tests"],"tags":["http-400","missing-parameter","languagetool-server"],"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-14T00:17:10.932Z"}