languagetool-org/languagetool · error · BadRequestException

Set only 'text' or 'data' parameter, not both

Error message

Set only 'text' or 'data' parameter, not both

What it means

/v2/check accepts the input either as plain 'text' or as structured 'data' (JSON annotation), never both, because the source of the annotated text would be ambiguous. Sending both throws BadRequestException (HTTP 400).

Source

Thrown at languagetool-server/src/main/java/org/languagetool/server/ApiV2.java:148

    String response = getConfigurationInfo(lang, config);
    ServerTools.setCommonHeaders(httpExchange, JSON_CONTENT_TYPE, allowOriginUrl);
    httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.getBytes(ENCODING).length);
    httpExchange.getResponseBody().write(response.getBytes(ENCODING));
    ServerMetricsCollector.getInstance().logResponse(HttpURLConnection.HTTP_OK);
  }

  private void handleSoftwareInfoRequest(HttpExchange httpExchange) throws IOException {
    String response = getSoftwareInfo();
    ServerTools.setCommonHeaders(httpExchange, JSON_CONTENT_TYPE, allowOriginUrl);
    httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.getBytes(ENCODING).length);
    httpExchange.getResponseBody().write(response.getBytes(ENCODING));
    ServerMetricsCollector.getInstance().logResponse(HttpURLConnection.HTTP_OK);
  }

  private void handleCheckRequest(HttpExchange httpExchange, Map<String, String> parameters, ErrorRequestLimiter errorRequestLimiter, String remoteAddress, HTTPServerConfig config) throws Exception {
    AnnotatedText aText;
    if (parameters.containsKey("text") && parameters.containsKey("data")) {
      throw new BadRequestException("Set only 'text' or 'data' parameter, not both");
    } else if (parameters.containsKey("text")) {
      aText = new AnnotatedTextBuilder().addText(parameters.get("text")).build();
    } else if (parameters.containsKey("data")) {
      ObjectMapper mapper = new ObjectMapper();
      JsonNode data;
      try {
        data = mapper.readTree(parameters.get("data"));
      } catch (JsonProcessingException e) {
        throw new BadRequestException("Could not parse JSON from 'data' parameter", e);
      }
      if (data.get("text") != null && data.get("annotation") != null) {
        throw new BadRequestException("'data' key in JSON requires either 'text' or 'annotation' key, not both");
      } else if (data.get("text") != null) {
        aText = getAnnotatedTextFromString(data, data.get("text").asText());
      } else if (data.get("annotation") != null) {
        aText = getAnnotatedTextFromJson(data);
      } else {
        throw new BadRequestException("'data' key in JSON requires 'text' or 'annotation' key");

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Remove either the 'text' or the 'data' parameter so only one remains
  2. Send plain text via 'text' or annotated content via 'data', not both
  3. Review client code for parameter defaults that inject 'text' alongside 'data'

Example fix

// before
curl -d 'text=Hello' -d 'data={"text":"Hello"}' --data-urlencode 'language=en-US' http://server:8081/v2/check
// after
curl -d 'text=Hello' --data-urlencode 'language=en-US' http://server:8081/v2/check
Defensive patterns

Strategy: validation

Validate before calling

const keys = ['text', 'data'].filter(k => k in payload);
if (keys.length === 2) throw new Error("Send only 'text' or 'data', not both");

Try / catch

try {
    const res = await check(params);
} catch (e) {
    if (/Set only 'text' or 'data'/.test(e.message)) {
        console.error('Remove the duplicate input parameter');
    } else throw e;
}

Prevention

When it happens

Trigger: POST /v2/check with both text=... and data=... in the same request body or query string.

Common situations: Client code adding a default text parameter while also forwarding a JSON data payload; proxy layers merging parameters.

Understand the failure class

Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.

Related errors


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