junit-team/junit5 · error · ExtensionConfigurationException

Either a valid time zone id or a TimeZoneProvider must be…

Error message

Either a valid time zone id or a TimeZoneProvider must be provided to DefaultTimeZone

What it means

ExtensionConfigurationException from DefaultTimeZoneExtension.validateCorrectConfiguration, raised when @DefaultTimeZone specifies neither a time-zone id (value empty) nor a timeZoneProvider (still the NullTimeZoneProvider default) — or specifies both. Exactly one of value or provider must be set.

Solutions

  1. Set exactly one: either value = "UTC" (a zone id) or timeZoneProvider = MyProvider.class.
  2. Remove the unused attribute so only one source of the TimeZone remains.

Example fix

// before
@DefaultTimeZone(value = "UTC", timeZoneProvider = MyProvider.class)
void test() {}
// after
@DefaultTimeZone("UTC")
void test() {}
Defensive patterns

Strategy: validation

Validate before calling

boolean noValue = annotation.value().isEmpty();
boolean noProvider = annotation.timeZoneProvider() == NullTimeZoneProvider.class;
if (noValue == noProvider) { /* must set exactly one */ }

Prevention

When it happens

Trigger: Annotating a test with @DefaultTimeZone (no attributes), or @DefaultTimeZone(value = "UTC", timeZoneProvider = MyProvider.class). The guard `noValue == noProvider` is true when both are absent or both are present.

Common situations: Adding @DefaultTimeZone as a marker expecting a default; specifying both a literal id and a provider 'just in case'; refactoring from one form to the other and leaving both populated.

Related errors


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

Appendix: source

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

				.map(DefaultTimeZoneExtension::createTimeZone);
	}

	private static TimeZone createTimeZone(DefaultTimeZone annotation) {
		validateCorrectConfiguration(annotation);

		if (!annotation.value().isEmpty()) {
			return createTimeZoneFromZoneId(annotation.value());
		}
		else {
			return createTimeZoneFromProvider(annotation.timeZoneProvider());
		}
	}

	private static void validateCorrectConfiguration(DefaultTimeZone annotation) {
		boolean noValue = annotation.value().isEmpty();
		boolean noProvider = annotation.timeZoneProvider() == NullTimeZoneProvider.class;
		if (noValue == noProvider) {
			throw new ExtensionConfigurationException(
				"Either a valid time zone id or a TimeZoneProvider must be provided to "
						+ DefaultTimeZone.class.getSimpleName());
		}
	}

	private static TimeZone createTimeZoneFromZoneId(String timeZoneId) {
		TimeZone configuredTimeZone = TimeZone.getTimeZone(timeZoneId);
		// TimeZone::getTimeZone returns with GMT as fallback if the given ID cannot be understood
		if (configuredTimeZone.equals(TimeZone.getTimeZone("GMT")) && !"GMT".equals(timeZoneId)) {
			throw new ExtensionConfigurationException("""
					@DefaultTimeZone not configured correctly.
					Could not find the specified time zone + '%s'.
					Please use correct identifiers, e.g. "GMT" for Greenwich Mean Time.
					""".formatted(timeZoneId));
		}
		return configuredTimeZone;
	}

View on GitHub (pinned to f070c699a0)