{"record":{"id":"cb8ca74b63aa2ffb","repo":"languagetool-org/languagetool","slug":"could-not-decode-query-query-length-request-met","errorCode":null,"errorMessage":"Could not decode query. Query length:  Request method: ","messagePattern":"Could not decode query\\. Query length:  Request method: ","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"languagetool-server/src/main/java/org/languagetool/server/LanguageToolHttpHandler.java","lineNumber":496,"sourceCode":"    if (query != null) {\n      parameters.putAll(getParameterMap(query, httpExchange));\n    }\n    return parameters;\n  }\n\n  private Map<String, String> getParameterMap(String query, HttpExchange httpExchange) throws UnsupportedEncodingException {\n    String[] pairs = StringUtils.split(query, '&');\n    Map<String, String> parameters = new HashMap<>();\n    for (String pair : pairs) {\n      int delimPos = pair.indexOf('=');\n      if (delimPos != -1) {\n        String param = pair.substring(0, delimPos);\n        String key = URLDecoder.decode(param, ENCODING);\n        try {\n          String value = URLDecoder.decode(pair.substring(delimPos + 1), ENCODING);\n          parameters.put(key, value);\n        } catch (IllegalArgumentException e) {\n          throw new BadRequestException(\"Could not decode query. Query length: \" + query.length() +\n                                     \" Request method: \" + httpExchange.getRequestMethod());\n        }\n      }\n    }\n    return parameters;\n  }\n\n}\n","sourceCodeStart":478,"sourceCodeEnd":505,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-server/src/main/java/org/languagetool/server/LanguageToolHttpHandler.java#L478-L505","documentation":"Thrown when URL-decoding of a query/body parameter fails because the value contains malformed percent-encoding (e.g. a lone '%' or invalid escape sequence). The server rejects the whole request as a BadRequest rather than skipping the bad parameter.","triggerScenarios":"GET query string or form body containing invalid URL-encoding such as '%' not followed by two hex digits, e.g. text=100% done without encoding the percent sign.","commonSituations":"Hand-built query strings where '%' characters are not escaped to %25, double-encoded values, clients sending raw bytes that aren't valid UTF-8 percent-escapes, or templates interpolating unsanitized user text into URLs.","solutions":["Percent-encode all parameter values (encode '%' as %25) before sending, e.g. with encodeURIComponent or curl --data-urlencode","Validate/fix the query string for stray '%' characters","Use an HTTP client library's form encoding instead of manual string concatenation"],"exampleFix":"// before\nfetch('/v2/check?text=' + text)\n// after\nfetch('/v2/check?text=' + encodeURIComponent(text))","handlingStrategy":"validation","validationCode":"function safeParam(v) {\n  const s = String(v);\n  if (/%(?![0-9A-Fa-f]{2})/.test(s)) throw new Error('Malformed percent-encoding: ' + s);\n  return encodeURIComponent(s);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await fetch(`/v2/check?text=${safeParam(text)}&language=en-US`);\n} catch (e) {\n  if (e.message.includes('Could not decode query')) {\n    console.error('Fix percent-encoding: escape % as %25');\n  }\n  throw e;\n}","preventionTips":["Always URL-encode parameter values with a standard encoder","Never build query strings by string concatenation of raw user text","Beware double-encoding when proxies also encode"],"tags":["http","languagetool","url-encoding"],"backgroundTag":"invalid-query-parameter","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"}