halo-dev/halo · warning · IllegalArgumentException
Locale "{locale}" cannot be used as it does not specify a la
Error message
Locale "{locale}" cannot be used as it does not specify a language. What it means
Thrown as IllegalArgumentException by LanguageUtils.computeLangFromLocale when the Locale has a blank language tag. The method builds resource-name candidates (_lang, _lang_COUNTRY, ...) and needs at least the language component to proceed.
Source
Thrown at application/src/main/java/run/halo/app/notification/LanguageUtils.java:29
*
* @author guqing
* @since 2.10.0
*/
@UtilityClass
public class LanguageUtils {
/**
* Compute all the possible languages we should use: *_gl_ES-gheada, *_gl_ES, _gl... from a given locale. The first
* element of the list is "default" if it can not find the language, use default.
*
* @param locale locale
* @return list of possible languages, from less specific to more specific.
*/
public static List<String> computeLangFromLocale(Locale locale) {
final List<String> resourceNames = new ArrayList<>(5);
if (StringUtils.isBlank(locale.getLanguage())) {
throw new IllegalArgumentException(
"Locale \"" + locale + "\" " + "cannot be used as it does not specify a language.");
}
resourceNames.add("default");
resourceNames.add(locale.getLanguage());
if (StringUtils.isNotBlank(locale.getCountry())) {
resourceNames.add(locale.getLanguage() + "_" + locale.getCountry());
}
if (StringUtils.isNotBlank(locale.getVariant())) {
resourceNames.add(locale.getLanguage() + "_" + locale.getCountry() + "-" + locale.getVariant());
}
return resourceNames;
}
}
View on GitHub (pinned to d2f5165f9c)
Solutions
- Fall back to a default Locale (e.g. Locale.ENGLISH or the system default) when the language is blank before calling computeLangFromLocale.
- Validate the Accept-Language/locale input and reject/normalize blank languages upstream.
- Use Locale.forLanguageTag with a checked, well-formed tag.
Example fix
// before List<String> langs = LanguageUtils.computeLangFromLocale(locale); // after Locale safe = StringUtils.isBlank(locale.getLanguage()) ? Locale.getDefault() : locale; List<String> langs = LanguageUtils.computeLangFromLocale(safe);
Defensive patterns
Strategy: validation
Validate before calling
Locale safe = (locale == null || StringUtils.isBlank(locale.getLanguage()))
? Locale.getDefault() : locale;
List<String> langs = LanguageUtils.computeLangFromLocale(safe); Type guard
static boolean localeHasLanguage(Locale l) {
return l != null && StringUtils.isNotBlank(l.getLanguage());
} Try / catch
try {
LanguageUtils.computeLangFromLocale(locale);
} catch (IllegalArgumentException e) {
// fall back to default language bundle
LanguageUtils.computeLangFromLocale(Locale.getDefault());
} Prevention
- Normalize blank-language Locales to a sensible default before resolving templates.
- Validate Accept-Language parsing output upstream.
- Never pass Locale.ROOT to language-resource resolution.
When it happens
Trigger: Calling computeLangFromLocale with a Locale whose getLanguage() is empty, e.g. new Locale("") or a Locale built from a country-only/variant-only string, or Locale.ROOT.
Common situations: Parsing an Accept-Language header that yields an empty language; defaulting to Locale.ROOT accidentally; constructing Locale from malformed input; a notification/template resolver receiving a blank locale.
Related errors
- validation.error.email.pattern
- validation.error.password.size
- validation.error.password.size
- Email must not be blank
- Locale "{}" cannot be used as it does not specify a language
AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14).
Data as JSON: /api/errors/fcf75aaa945a98ff.
Report an issue: GitHub.