{"record":{"id":"dd211f9f05680318","repo":"languagetool-org/languagetool","slug":"you-specified-altlanguage-langcode-but-for-th","errorCode":null,"errorMessage":"You specified altLanguage '{langCode}', but for this language you need to specify a variant, e.g. 'en-GB' instead of just 'en'","messagePattern":"You specified altLanguage '(.+?)', but for this language you need to specify a variant, e\\.g\\. 'en-GB' instead of just 'en'","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"languagetool-server/src/main/java/org/languagetool/server/TextChecker.java","lineNumber":540,"sourceCode":"    Integer count = languageCheckCounts.get(lang.getShortCodeWithCountryAndVariant());\n    if (count == null) {\n      count = 1;\n    } else {\n      count++;\n    }\n    //print(\"Starting check: \" + aText.getPlainText().length() + \" chars, #\" + count);\n    String motherTongueParam = params.get(\"motherTongue\");\n    Language motherTongue = motherTongueParam != null ? parseLanguage(motherTongueParam) : null;\n    boolean useEnabledOnly = \"yes\".equals(params.get(\"enabledOnly\")) || \"true\".equals(params.get(\"enabledOnly\"));\n    List<Language> altLanguages = new ArrayList<>();\n    if (params.get(\"altLanguages\") != null) {\n      String[] altLangParams = COMMA_WHITESPACE_PATTERN.split(params.get(\"altLanguages\"));\n      for (String langCode : altLangParams) {\n        Language altLang = parseLanguage(langCode);\n        altLanguages.add(altLang);\n        if (altLang.hasVariant() && !altLang.isVariant()) {\n          ServerMetricsCollector.getInstance().logRequestError(ServerMetricsCollector.RequestErrorType.INVALID_REQUEST);\n          throw new BadRequestException(\"You specified altLanguage '\" + langCode + \"', but for this language you need to specify a variant, e.g. 'en-GB' instead of just 'en'\");\n        }\n      }\n    }\n    List<String> enabledRules = getEnabledRuleIds(params);\n    List<String> disabledRules = getDisabledRuleIds(params);\n    List<CategoryId> enabledCategories = getCategoryIds(\"enabledCategories\", params);\n    List<CategoryId> disabledCategories = getCategoryIds(\"disabledCategories\", params);\n\n\n    if (shouldRunRestrictedRulesTest(params, agent, lang, abTest)) {\n      log.info(\"Running test with restricted rules for user: {}, language: {}, client: {}\",\n        params.getOrDefault(\"username\", \"\"), lang.getShortCodeWithCountryAndVariant(), agent);\n      useEnabledOnly = true;\n      enabledRules = onlyTestRules;\n      // need to clear these settings, leads to conflict with useEnabledOnly otherwise\n      disabledRules = Collections.emptyList();\n      disabledCategories = Collections.emptyList();\n    }","sourceCodeStart":522,"sourceCodeEnd":558,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-server/src/main/java/org/languagetool/server/TextChecker.java#L522-L558","documentation":"Some languages in LanguageTool exist only as variants (e.g. English en-GB/en-US). When an altLanguages entry names such a language without an explicit variant, checkText rejects the request with BadRequestException because the alt language cannot be instantiated unambiguously.","triggerScenarios":"Sending altLanguages=en (or altLanguages=pt) where the parsed Language has hasVariant()==true but isVariant()==false — i.e. a bare short code for a variant-only language — in the /v2/check request.","commonSituations":"Users writing altLanguages=en assuming it covers all English; while the main 'language' parameter accepts bare codes for some setups, altLanguages demands fully specified variants; older client examples predate stricter validation.","solutions":["Replace the bare code with a specific variant, e.g. altLanguages=en-GB instead of en","List each needed variant explicitly (altLanguages=en-US,en-GB,pt-BR)","Check Languages.getLanguageForShortCode to see which codes require a variant before building the request"],"exampleFix":"// before\ncurl -d text=... -d language=de-DE -d altLanguages=en http://server/v2/check\n// after\ncurl -d text=... -d language=de-DE -d altLanguages=en-GB http://server/v2/check","handlingStrategy":"validation","validationCode":"const VARIANT_ONLY = ['en','de','pt','ca','nl']; // languages requiring variants\nfor (const code of (params.altLanguages || '').split(',')) {\n  if (VARIANT_ONLY.includes(code.trim())) {\n    throw new Error(`altLanguage '${code}' needs a variant, e.g. ${code}-GB`);\n  }\n}","typeGuard":"function isFullVariant(code) {\n  return typeof code === 'string' && /^[a-z]{2,3}-[A-Za-z]{2,4}$/.test(code.trim());\n}","tryCatchPattern":null,"preventionTips":["Always pass full variant codes in altLanguages (en-GB, pt-BR)","Query /v2/languages to learn which codes are variant-only","Validate altLanguages entries client-side before building the request"],"tags":["http-400","query-parameters","language-variants"],"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"}