languagetool-org/languagetool · error · BadRequestException
Invalid 'preferredVariants', no such language/variant found:
Error message
Invalid 'preferredVariants', no such language/variant found: '{preferredVariant}' What it means
The preferredVariants entry has a valid 'xx-YY' shape but LanguageTool has no registered language/variant matching it. parseLanguage() returns null for unknown combinations, so the server throws this BadRequestException. The language part must match the request's short code for this branch to apply.
Source
Thrown at languagetool-server/src/main/java/org/languagetool/server/TextChecker.java:1023
} else {
lang = detected.getDetectedLanguage();
}
//String mode;
//long t1 = System.nanoTime();
//long t2 = System.nanoTime();
//float runTime = (t2-t1)/1000.0f/1000.0f;
//System.out.printf(Locale.ENGLISH, "detected " + detected + " using " + mode + " in %.2fms for %d chars\n", runTime, text.length());
if (preferredVariants.size() > 0) {
for (String preferredVariant : preferredVariants) {
if (!preferredVariant.contains("-")) {
throw new BadRequestException("Invalid format for 'preferredVariants', expected a dash as in 'en-GB': '" + preferredVariant + "'");
}
String preferredVariantLang = preferredVariant.split("-")[0];
if (preferredVariantLang.equals(lang.getShortCode())) {
lang = parseLanguage(preferredVariant);
if (lang == null) {
throw new BadRequestException("Invalid 'preferredVariants', no such language/variant found: '" + preferredVariant + "'");
}
}
}
} else {
if (lang.getDefaultLanguageVariant() != null) {
lang = lang.getDefaultLanguageVariant();
}
}
return new DetectedLanguage(null, lang, detected != null ? detected.getDetectionConfidence() : 0f,
detected != null ? detected.getDetectionSource() : null);
}
static class QueryParams {
final List<Language> altLanguages;
final List<String> enabledRules;
final List<String> disabledRules;
final List<CategoryId> enabledCategories;
final List<CategoryId> disabledCategories;View on GitHub (pinned to 2e990059ce)
Solutions
- Verify the exact variant exists, e.g. use en-GB not en-UK
- List available variants via the /v2/languages endpoint and pick from it
- Validate user input against the supported language list before sending
- Check the variant's language prefix matches your 'language' parameter
Example fix
// before
params.put("preferredVariants", "en-UK");
// after
params.put("preferredVariants", "en-GB"); Defensive patterns
Strategy: validation
Validate before calling
const supported = await fetch(`${LT_URL}/v2/languages`).then(r => r.json());
const valid = supported.some(l => `${l.code}-${l.code.toUpperCase()}` === variant || l.name === variant); Type guard
const isKnownVariant = (v, list) => list.includes(v);
Try / catch
try { const res = await check(params); } catch (e) { if (e.status === 400 && /no such language\/variant/.test(e.message)) { /* fall back to default variant */ } } Prevention
- Use en-GB not en-UK
- Derive choices from /v2/languages rather than hardcoding
- Pin the server version when hardcoding variant lists
When it happens
Trigger: Calling /v2/check with e.g. preferredVariants=en-XX, xx-YY or zz-FAKE, or a variant that exists for another language than the current lang short code path resolves; typos like 'en-GBB'.
Common situations: Misspelled variant codes; inventing variants that don't exist (en-UK — the correct code is en-GB); stale hardcoded lists after LanguageTool upgrades; user-supplied locale strings passed through unvalidated.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Only either 'text' or 'markup' are supported in an object in
- 'text' cannot be used with 'interpretAs' (only 'markup' can)
- Only 'text' and 'markup' are supported in 'annotation' list:
- Invalid format for 'preferredVariants', expected a dash as i
- You specified 'preferredVariants' but you didn't specify 'la
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/3535cf2b74af79b5.
Report an issue: GitHub.