languagetool-org/languagetool · error · AuthException

Anonymous access is prohibited on this server, please provid

Error message

Anonymous access is prohibited on this server, please provide authentication.

What it means

The server is configured with a limit (e.g. -X 'maximum text length' / anonymousAccess disallowed) that forbids unauthenticated requests. checkText throws AuthException when no premium UID (from authentication) is supplied and the config disallows anonymous access.

Source

Thrown at languagetool-server/src/main/java/org/languagetool/server/TextChecker.java:405

      httpExchange.getResponseBody().write(response.getBytes(ENCODING));
      return;
    }

    String requestId = httpExchange.getRequestHeaders().getFirst("X-Request-ID");

    // logging information
    String agent = params.get("useragent") != null ? params.get("useragent") : "-";
    Long agentId = null, userId = null;
    if (databaseLogger.isLogging()) {
      DatabaseAccess db = DatabaseAccess.getInstance();
      agentId = db.getOrCreateClientId(params.get("useragent"));
      userId = limits.getPremiumUid();
    }
    String referrer = httpExchange.getRequestHeaders().getFirst("Referer");
    String userAgent = httpExchange.getRequestHeaders().getFirst("User-Agent");

    if (!config.isAnonymousAccessAllowed() && limits.getPremiumUid() == null) {
      throw new AuthException("Anonymous access is prohibited on this server, please provide authentication.");
    }

    int length = aText.getPlainText().length();
    if ("true".equals(params.get("languageChanged"))) {
      log.info("languageChanged to " + params.get("language") + " for text with length " + aText.getPlainText().trim().length());
    }
    if (length > limits.getMaxTextLength()) {
      ServerMetricsCollector.getInstance().logRequestError(ServerMetricsCollector.RequestErrorType.MAX_TEXT_SIZE);
      throw new TextTooLongException("Your text exceeds the limit of " + limits.getMaxTextLength() +
              " characters (it's " + length + " characters). Please submit a shorter text.");
    }
    // static because we can't rely on errorRequestLimiter, null when timeoutRequestLimit option not set
    if (!config.isLocalApiMode()) {
      try {
        RequestLimiter.checkUserLimit(referrer, userAgent, limits);
      } catch (TooManyRequestsException e) {
        String response = "Error: Access denied: " + e.getMessage();
        httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_FORBIDDEN, response.getBytes(ENCODING).length);

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Send authentication with the request (username/password/token parameters or Basic auth header) to obtain a premium UID
  2. Start the server with anonymous access allowed (e.g. do not set the 'no anonymous' option / set the option permitting public access) if this is intended to be a public server
  3. Point the client at a server instance whose access policy matches your use case

Example fix

// before
curl -d text=... -d language=en-US http://server/v2/check
// after
curl -u user:token -d text=... -d language=en-US http://server/v2/check
Defensive patterns

Strategy: validation

Validate before calling

if (!credentials.username || !credentials.token) {
  throw new Error('This server requires authentication; supply username/token before calling /v2/check');
}

Type guard

function hasAuth(c) {
  return c != null && typeof c === 'object' && typeof c.username === 'string' && c.username.length > 0 && typeof c.token === 'string' && c.token.length > 0;
}

Try / catch

try {
  return await check(text, { auth });
} catch (e) {
  if (e.status === 401 || /Anonymous access is prohibited/.test(e.message)) {
    throw new AuthRequiredError('Configure credentials for this LanguageTool server');
  }
  throw e;
}

Prevention

When it happens

Trigger: POSTing to /v2/check (directly or via testPipelineCreatedAndUsed/testJSONP-style callers) without valid credentials (username/password, API token) on a server started without the anonymousAccess option, so limits.getPremiumUid() is null and config.isAnonymousAccessAllowed() is false.

Common situations: Running a private LanguageTool server with authentication enforced but calling it from a script or browser app that never sends the Basic auth header; CI tests hitting a locked-down production instance.

Understand the failure class

Related errors


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