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
- Add the username parameter that pairs with the password
- If migrating to API keys, send username + apiKey instead of password
- 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
- Load username and password from the same config section/secret
- Check for empty/undefined username before sending password-based auth
- Prefer apiKey auth (username + apiKey) over legacy passwords
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
- With 'username' set, you also need to specify 'apiKey'
- apiKey was set, but username was not: {apiKey}
- apiKey AND password was set, set only apiKey
- Expected Basic Authentication
- This end point needs a user id
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/b70bf36704f8d5bd.
Report an issue: GitHub.