junit-team/junit5 · error · ExtensionConfigurationException

@DefaultLocale can only be used with language tag if…

Error message

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

What it means

ExtensionConfigurationException from DefaultLocaleExtension.createFromLanguageTag, raised when @DefaultLocale is given a language tag (the value() attribute) but one or more of language, country, variant, or a custom localeProvider are also set. The annotation is mutually exclusive: a BCP-47 tag cannot be combined with explicit parts or a provider.

Solutions

  1. Use ONLY the value language tag: @DefaultLocale("en-US") and remove language/country/variant/localeProvider.
  2. OR switch fully to the parts form: drop value and set language (and optionally country/variant).
  3. Audit the annotation to ensure exactly one configuration style is present.

Example fix

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

Strategy: validation

Validate before calling

boolean hasTag = !annotation.value().isEmpty();
boolean hasParts = !annotation.language().isEmpty() || !annotation.country().isEmpty()
        || !annotation.variant().isEmpty();
boolean hasProvider = annotation.localeProvider() != NullLocaleProvider.class;
if (hasTag && (hasParts || hasProvider)) {
    // pick one style
}

Prevention

When it happens

Trigger: Annotating a test with @DefaultLocale(value = "en-US", language = "en") (or with country/variant/localeProvider populated). createFromLanguageTag is selected whenever value() is non-empty, and the guard rejects any other populated field.

Common situations: Copy-pasting @DefaultLocale examples and leaving defaults; incrementally adding country= after first using a tag; mixing the tag-based and parts-based styles during refactoring.

Related errors


AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11). Data as JSON: /api/errors/e39403a9f01d22c0. Report an issue: GitHub.

Appendix: 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 f070c699a0)