languagetool-org/languagetool · error · BadRequestException

password was set, but username was not

Error message

password was set, but username was not

What it means

Parameter validation in ServerTools.getUserLimits: a password was supplied without a username, so credential-based user limits lookup cannot proceed.

Source

Thrown at languagetool-server/src/main/java/org/languagetool/server/ServerTools.java:164

      }
      if (params.get("apiKey") != null) {
        return UserLimits.getLimitsByApiKey(config, params.get("username"), params.get("apiKey"));
      } else if (params.get("password") != null) {
        return UserLimits.getLimitsFromUserAccount(config, params.get("username"), params.get("password"));
      } else if (params.get("tokenV2") != null) {
        if (authHeader != null) {
          return UserLimits.getLimitsWithJwtToken(config, authHeader, params.get("username"), params.get("tokenV2"));
        }
        return UserLimits.getLimitsByAddonToken(config, params.get("username"), params.get("tokenV2"));
      } else {
        throw new BadRequestException("With 'username' set, you also need to specify 'apiKey'");
      }
    } else {
      if (params.get("apiKey") != null) {
        throw new BadRequestException("apiKey was set, but username was not: " + params.get("apiKey"));
      }
      if (params.get("password") != null) {
        throw new BadRequestException("password was set, but username was not");
      }
      if (authHeader != null) {
        return UserLimits.getLimitsWithJwtToken(config, authHeader, params.get("username"), params.get("tokenV2"));
      }
      return UserLimits.getDefaultLimits(config);
    }
  }

  @NotNull
  static Mode getMode(Map<String, String> params) {
    Mode mode;
    if (params.get("mode") != null) {
      String modeParam = params.get("mode");
      if ("textLevelOnly".equals(modeParam)) {
        mode = Mode.TEXTLEVEL_ONLY;
      } else if ("allButTextLevelOnly".equals(modeParam)) {
        mode = Mode.ALL_BUT_TEXTLEVEL_ONLY;
      } else if ("all".equals(modeParam)) {

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Add the username parameter that pairs with the password
  2. If migrating to API keys, send username + apiKey instead of password
  3. Fix credential loading so username and password are taken from the same complete configuration

Example fix

// before
params.put("password", pwd);
// after
params.put("username", user); params.put("password", pwd);
Defensive patterns

Strategy: validation

Validate before calling

function validateAuthParams(params) {
  if (params.password && !params.username) {
    throw new Error("'password' requires 'username'");
  }
}

Try / catch

try {
  return await lt.check(params);
} catch (e) {
  if (e.status === 400 && /password was set, but username was not/.test(e.message)) {
    throw new ConfigError('Incomplete credentials: username missing');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling /v2/check with password=... but no username parameter (and no apiKey).

Common situations: Legacy username/password clients where the username field was dropped or renamed; partial credential loading from config (password present, username empty); form submissions missing the username input.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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