languagetool-org/languagetool · error · BadRequestException

<url> needs to be called with GET

Error message

<url> needs to be called with GET

What it means

ensureGetMethod guards endpoints that only support GET (e.g. /words, /ruleExamples, /users/me). If the request method is not GET (case-insensitive), it throws a BadRequestException of the form '<url> needs to be called with GET'.

Source

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

      if (userInfo != null) {
        if (format.equals("minimal")) {
          StringWriter sw = new StringWriter();
          new ObjectMapper().writeValue(sw, userInfo);
          sendJson(httpExchange, sw);
        } else {
          StringWriter sw = new StringWriter();
          new ObjectMapper().writeValue(sw, DatabaseAccess.getInstance().getExtendedUserInfo(user));
          sendJson(httpExchange, sw);
        }
      } else {
        throw new IllegalStateException("Could not fetch user information");
      }
    }
  }

  private void ensureGetMethod(HttpExchange httpExchange, String url) {
    if (!httpExchange.getRequestMethod().equalsIgnoreCase("get")) {
      throw new BadRequestException(url + " needs to be called with GET");
    }
  }
  
  private void ensurePostMethod(HttpExchange httpExchange, String url) {
    if (!httpExchange.getRequestMethod().equalsIgnoreCase("post")) {
      throw new BadRequestException(url + " needs to be called with POST");
    }
  }

  @NotNull
  private UserLimits getUserLimits(Map<String, String> parameters, HTTPServerConfig config) {
    UserLimits limits = ServerTools.getUserLimits(parameters, config);
    if (limits.getPremiumUid() == null) {
      throw new BadRequestException("This end point needs a user id");
    }
    return limits;
  }

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Send the request with the GET method instead of POST/PUT/DELETE.
  2. Move any parameters from the request body into the URL query string.
  3. Check redirect handling — some clients convert GET to POST on 307/308; re-issue as GET.

Example fix

// before
curl -X POST 'https://server/v2/ruleExamples?lang=en-US&ruleId=X'
// after
curl 'https://server/v2/ruleExamples?lang=en-US&ruleId=X'
Defensive patterns

Strategy: validation

Validate before calling

if (method.toUpperCase() !== 'GET') throw new Error(`${url} must be called with GET; move params into the query string`);

Prevention

When it happens

Trigger: POST to /v2/words, /v2/ruleExamples or /v2/users/me; PUT/DELETE calls generated by a generic REST client; follow-up redirects that change the method.

Common situations: Clients assuming all endpoints accept POST like /v2/check; REST frameworks auto-routing reads as POST with an _method override that the server ignores.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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