languagetool-org/languagetool · error · BadRequestException

Could not decode query. Query length: Request method:

Error message

Could not decode query. Query length:  Request method: 

What it means

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.

Source

Thrown at languagetool-server/src/main/java/org/languagetool/server/LanguageToolHttpHandler.java:496

    if (query != null) {
      parameters.putAll(getParameterMap(query, httpExchange));
    }
    return parameters;
  }

  private Map<String, String> getParameterMap(String query, HttpExchange httpExchange) throws UnsupportedEncodingException {
    String[] pairs = StringUtils.split(query, '&');
    Map<String, String> parameters = new HashMap<>();
    for (String pair : pairs) {
      int delimPos = pair.indexOf('=');
      if (delimPos != -1) {
        String param = pair.substring(0, delimPos);
        String key = URLDecoder.decode(param, ENCODING);
        try {
          String value = URLDecoder.decode(pair.substring(delimPos + 1), ENCODING);
          parameters.put(key, value);
        } catch (IllegalArgumentException e) {
          throw new BadRequestException("Could not decode query. Query length: " + query.length() +
                                     " Request method: " + httpExchange.getRequestMethod());
        }
      }
    }
    return parameters;
  }

}

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Percent-encode all parameter values (encode '%' as %25) before sending, e.g. with encodeURIComponent or curl --data-urlencode
  2. Validate/fix the query string for stray '%' characters
  3. Use an HTTP client library's form encoding instead of manual string concatenation

Example fix

// before
fetch('/v2/check?text=' + text)
// after
fetch('/v2/check?text=' + encodeURIComponent(text))
Defensive patterns

Strategy: validation

Validate before calling

function safeParam(v) {
  const s = String(v);
  if (/%(?![0-9A-Fa-f]{2})/.test(s)) throw new Error('Malformed percent-encoding: ' + s);
  return encodeURIComponent(s);
}

Try / catch

try {
  return await fetch(`/v2/check?text=${safeParam(text)}&language=en-US`);
} catch (e) {
  if (e.message.includes('Could not decode query')) {
    console.error('Fix percent-encoding: escape % as %25');
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06). Data as JSON: /api/errors/cb8ca74b63aa2ffb. Report an issue: GitHub.