{"record":{"id":"b70bf36704f8d5bd","repo":"languagetool-org/languagetool","slug":"password-was-set-but-username-was-not","errorCode":null,"errorMessage":"password was set, but username was not","messagePattern":"password was set, but username was not","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"languagetool-server/src/main/java/org/languagetool/server/ServerTools.java","lineNumber":164,"sourceCode":"      }\n      if (params.get(\"apiKey\") != null) {\n        return UserLimits.getLimitsByApiKey(config, params.get(\"username\"), params.get(\"apiKey\"));\n      } else if (params.get(\"password\") != null) {\n        return UserLimits.getLimitsFromUserAccount(config, params.get(\"username\"), params.get(\"password\"));\n      } else if (params.get(\"tokenV2\") != null) {\n        if (authHeader != null) {\n          return UserLimits.getLimitsWithJwtToken(config, authHeader, params.get(\"username\"), params.get(\"tokenV2\"));\n        }\n        return UserLimits.getLimitsByAddonToken(config, params.get(\"username\"), params.get(\"tokenV2\"));\n      } else {\n        throw new BadRequestException(\"With 'username' set, you also need to specify 'apiKey'\");\n      }\n    } else {\n      if (params.get(\"apiKey\") != null) {\n        throw new BadRequestException(\"apiKey was set, but username was not: \" + params.get(\"apiKey\"));\n      }\n      if (params.get(\"password\") != null) {\n        throw new BadRequestException(\"password was set, but username was not\");\n      }\n      if (authHeader != null) {\n        return UserLimits.getLimitsWithJwtToken(config, authHeader, params.get(\"username\"), params.get(\"tokenV2\"));\n      }\n      return UserLimits.getDefaultLimits(config);\n    }\n  }\n\n  @NotNull\n  static Mode getMode(Map<String, String> params) {\n    Mode mode;\n    if (params.get(\"mode\") != null) {\n      String modeParam = params.get(\"mode\");\n      if (\"textLevelOnly\".equals(modeParam)) {\n        mode = Mode.TEXTLEVEL_ONLY;\n      } else if (\"allButTextLevelOnly\".equals(modeParam)) {\n        mode = Mode.ALL_BUT_TEXTLEVEL_ONLY;\n      } else if (\"all\".equals(modeParam)) {","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-server/src/main/java/org/languagetool/server/ServerTools.java#L146-L182","documentation":"Parameter validation in ServerTools.getUserLimits: a password was supplied without a username, so credential-based user limits lookup cannot proceed.","triggerScenarios":"Calling /v2/check with password=... but no username parameter (and no apiKey).","commonSituations":"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.","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"],"exampleFix":"// before\nparams.put(\"password\", pwd);\n// after\nparams.put(\"username\", user); params.put(\"password\", pwd);","handlingStrategy":"validation","validationCode":"function validateAuthParams(params) {\n  if (params.password && !params.username) {\n    throw new Error(\"'password' requires 'username'\");\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await lt.check(params);\n} catch (e) {\n  if (e.status === 400 && /password was set, but username was not/.test(e.message)) {\n    throw new ConfigError('Incomplete credentials: username missing');\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["http","bad-request","authentication","missing-parameter","languagetool"],"backgroundTag":"missing-required-argument","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}