{"record":{"id":"154741eda3af0341","repo":"languagetool-org/languagetool","slug":"e-getmessage-invalid-language-code-passed-to","errorCode":null,"errorMessage":"{e.getMessage()} (invalid language code passed to Languages.getLanguageForShortCode)","messagePattern":"(.+?) \\(invalid language code passed to Languages\\.getLanguageForShortCode\\)","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"languagetool-server/src/main/java/org/languagetool/server/TextChecker.java","lineNumber":265,"sourceCode":"      long start = System.currentTimeMillis();\n      prewarmPipelinePool();\n      long end = System.currentTimeMillis();\n      log.info(\"Prewarming finished in {} seconds.\", (end - start) / 1000.0);\n    }\n    if (config.getAbTest() != null) {\n      UserConfig.enableABTests();\n      log.info(\"A/B-Test enabled: \" + config.getAbTest());\n      if (config.getAbTest().equals(\"SuggestionsOrderer\")) {\n        SuggestionsOrdererConfig.setMLSuggestionsOrderingEnabled(true);\n      }\n    }\n  }\n\n  protected static Language parseLanguage(String code) throws BadRequestException {\n    try {\n      return Languages.getLanguageForShortCode(code);\n    } catch (IllegalArgumentException e) {\n      throw new BadRequestException(e.getMessage());\n    }\n  }\n\n  /**\n   * Hash a string deterministically into a 64-bit signed long; use textSessionIdParam if set, fall back to client IP.\n   */\n  protected static Long computeTextSessionID(String textSessionIdParam, String ip) {\n      String input = textSessionIdParam != null ? textSessionIdParam : ip;\n      if (input == null) {\n        return null;\n      }\n      try {\n        MessageDigest md = MessageDigest.getInstance(\"SHA-256\");\n        byte[] bytes = md.digest(input.getBytes(StandardCharsets.UTF_8));\n\n        ByteBuffer buffer = ByteBuffer.wrap(bytes);\n        Long textSessionId = buffer.getLong();\n        return textSessionId;","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-server/src/main/java/org/languagetool/server/TextChecker.java#L247-L283","documentation":"LanguageTool's server wraps the IllegalArgumentException thrown by Languages.getLanguageForShortCode when a request's 'language' (or related) parameter is not a recognized language/variant short code. It is re-thrown as a BadRequestException with HTTP 400 semantics, so the caller sent an unsupported language identifier.","triggerScenarios":"Passing an unknown or malformed code to the /v2/check endpoint's language, motherTongue, altLanguages, sourceLanguage parameters, or language=auto variant parameters, e.g. language='xx' or 'english' instead of 'en-US'. Also thrown via parseLanguage from getLanguageVariantForCode and detectLanguageOfString paths.","commonSituations":"Typos in the language code, using a display name instead of a code, requesting a language variant that is not registered in the server build, or a client built for a newer LanguageTool version requesting a language the server does not support.","solutions":["Check the code against Languages.getLanguageForShortCode / the server's supported language list (GET /v2/languages)","Use the exact short code including the variant, e.g. 'en-US', 'pt-BR', not just 'en' or a display name","Trim whitespace and URL-encode the language parameter correctly in the HTTP request","If the language truly is missing, build/register a language module or use a close existing variant"],"exampleFix":"// before\nPOST /v2/check  language=english\n// after\nPOST /v2/check  language=en-US","handlingStrategy":"validation","validationCode":"const SUPPORTED = await fetch(baseUrl + '/v2/languages').then(r => r.json());\nfunction isValidLangCode(code) {\n  return SUPPORTED.some(l => l.code === code || code.startsWith(l.code + '-'));\n}\nif (!isValidLangCode(params.language)) throw new Error(`Unsupported language code: ${params.language}`);","typeGuard":"function isLangCode(v) {\n  return typeof v === 'string' && /^[a-z]{2,3}(-[A-Z]{2}|-[a-z]{2,4})?$/.test(v.trim());\n}","tryCatchPattern":"try {\n  const res = await check(text, lang);\n} catch (e) {\n  if (e.status === 400 && /invalid language/i.test(e.message)) {\n    lang = 'en-US'; // fallback to a known-supported code\n  } else throw e;\n}","preventionTips":["Fetch /v2/languages once and validate codes against it","Always use full variant codes like en-US when variants exist","Trim and URL-encode the language parameter","Pin client and server LanguageTool versions so language sets match"],"tags":["http-400","language-detection","languagetool"],"backgroundTag":"invalid-argument-value","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"}