junit-team/junit5 · error · ExtensionConfigurationException

@DefaultLocale can only be used with language tag if languag

Error message

@DefaultLocale can only be used with language tag if language, country, variant and provider are not set

What it means

Thrown as ExtensionConfigurationException by DefaultLocaleExtension.createFromLanguageTag when @DefaultLocale is configured with the 'value' (language tag) attribute AND any of language, country, variant, or a non-default localeProvider are also set. The 'value' attribute must be used alone — it maps to Locale.forLanguageTag and is mutually exclusive with the parts-based and provider-based configuration modes.

Source

Thrown at junit-jupiter-api/src/main/java/org/junit/jupiter/api/util/DefaultLocaleExtension.java:73

				.map(DefaultLocaleExtension::createLocale);
	}

	private static Locale createLocale(DefaultLocale annotation) {
		if (!annotation.value().isEmpty()) {
			return createFromLanguageTag(annotation);
		}
		else if (!annotation.language().isEmpty()) {
			return createFromParts(annotation);
		}
		else {
			return getFromProvider(annotation);
		}
	}

	private static Locale createFromLanguageTag(DefaultLocale annotation) {
		if (!annotation.language().isEmpty() || !annotation.country().isEmpty() || !annotation.variant().isEmpty()
				|| annotation.localeProvider() != NullLocaleProvider.class) {
			throw new ExtensionConfigurationException(
				"@DefaultLocale can only be used with language tag if language, country, variant and provider are not set");
		}
		return Locale.forLanguageTag(annotation.value());
	}

	private static Locale createFromParts(DefaultLocale annotation) {
		if (annotation.localeProvider() != NullLocaleProvider.class)
			throw new ExtensionConfigurationException(
				"@DefaultLocale can only be used with language tag if provider is not set");
		String language = annotation.language();
		String country = annotation.country();
		String variant = annotation.variant();
		if (!language.isEmpty() && !country.isEmpty() && !variant.isEmpty()) {
			return JupiterLocaleUtils.createLocale(language, country, variant);
		}
		else if (!language.isEmpty() && !country.isEmpty()) {
			return JupiterLocaleUtils.createLocale(language, country);
		}

View on GitHub (pinned to 956246301e)

Solutions

  1. Use ONLY value= with a BCP-47 language tag: @DefaultLocale(value = "en-US").
  2. If you need parts-based configuration, remove value= and use language=/country=/variant=.
  3. If you need a provider, remove value=, language=, country=, variant= and set only localeProvider=.

Example fix

// before
@DefaultLocale(value = "en-US", language = "en", country = "US")
void test() {}

// after — pick ONE mode; here the BCP-47 tag form
@DefaultLocale(value = "en-US")
void test() {}
Defensive patterns

Strategy: validation

Validate before calling

// Inspect the annotation before the test runs (e.g. in a static check)
DefaultLocale d = testClass.getAnnotation(DefaultLocale.class);
boolean valueSet = !d.value().isEmpty();
boolean partsSet = !d.language().isEmpty() || !d.country().isEmpty() || !d.variant().isEmpty();
boolean providerSet = d.localeProvider() != NullLocaleProvider.class;
if (valueSet && (partsSet || providerSet)) {
    throw new IllegalStateException("@DefaultLocale value= cannot be combined with parts or provider");
}

Prevention

When it happens

Trigger: Annotating a test with @DefaultLocale(value = "en-US", language = "en"), or @DefaultLocale(value = "en-US", country = "US"), or @DefaultLocale(value = "en-US", localeProvider = MyProvider.class). Any combination of value with another attribute triggers it.

Common situations: Copy-pasting a @DefaultLocale declaration and adding value= on top of an existing language=/country= configuration; misunderstanding that value= is the BCP-47 tag form and cannot be mixed with the parts form.

Related errors


AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04). Data as JSON: /data/errors/e39403a9f01d22c0.json. Report an issue: GitHub.