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.
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
- Invalid format for 'preferredVariants', expected a dash as…
- Only either 'text' or 'markup' are supported in an object…
- Only 'text' and 'markup' are supported in 'annotation'…
- 'text' cannot be used with 'interpretAs' (only 'markup'…
- You specified 'preferredVariants' but you didn't specify…
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/3535cf2b74af79b5.
Report an issue: GitHub.
Appendix: 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)