junit-team/junit5 · error · ExtensionConfigurationException

Could not instantiate TimeZoneProvider because of exception

Error message

Could not instantiate TimeZoneProvider because of exception

What it means

ExtensionConfigurationException from DefaultTimeZoneExtension.createTimeZoneFromProvider, raised when the configured TimeZoneProvider class cannot be instantiated via ReflectionSupport.newInstance. Any exception during class loading or construction (no usable constructor, inaccessible class, constructor throwing) is wrapped and rethrown.

Solutions

  1. Add a public no-argument constructor to the TimeZoneProvider class.
  2. Make the class public and top-level (or public static nested).
  3. Move logic that can fail out of the constructor into get().
  4. Inspect the wrapped cause for the specific reflection error.

Example fix

// before
class MyProvider implements TimeZoneProvider {
    public MyProvider(Config c) { /* ... */ }
    public TimeZone get() { return TimeZone.getTimeZone("UTC"); }
}
// after
public class MyProvider implements TimeZoneProvider {
    public MyProvider() {}
    public TimeZone get() { return TimeZone.getTimeZone("UTC"); }
}
Defensive patterns

Strategy: validation

Validate before calling

Class<? extends TimeZoneProvider> c = annotation.timeZoneProvider();
int mods = c.getModifiers();
if (Modifier.isAbstract(mods) || !Modifier.isPublic(mods)) { /* fix visibility */ }
if (Arrays.stream(c.getConstructors()).noneMatch(con -> con.getParameterCount() == 0)) { /* add no-arg ctor */ }

Type guard

static boolean instantiableTimeZoneProvider(Class<?> c) {
    int m = c.getModifiers();
    return Modifier.isPublic(m) && !Modifier.isAbstract(m)
        && Arrays.stream(c.getConstructors()).anyMatch(con -> con.getParameterCount() == 0);
}

Prevention

When it happens

Trigger: Specifying @DefaultTimeZone(timeZoneProvider = MyProvider.class) where MyProvider lacks a public no-arg constructor, is non-public/abstract, or its constructor throws.

Common situations: Provider with only a parameterized constructor; non-static nested provider class; constructor doing I/O or env access that fails; provider not exported in a modular setup.

Related errors


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

Appendix: source

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

		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;
	}

	private static TimeZone createTimeZoneFromProvider(Class<? extends TimeZoneProvider> providerClass) {
		try {
			TimeZoneProvider provider = ReflectionSupport.newInstance(providerClass);
			return Optional.ofNullable(provider.get()).orElse(TimeZone.getTimeZone("GMT"));
		}
		catch (Exception exception) {
			throw new ExtensionConfigurationException("Could not instantiate TimeZoneProvider because of exception",
				exception);
		}
	}

	@Override
	public void afterEach(ExtensionContext context) {
		load(context, DEFAULT_KEY).ifPresent(TimeZone::setDefault);
	}

	private static void store(ExtensionContext context, String key, TimeZone value) {
		getStore(context).put(key, value);
	}

	private static Optional<TimeZone> load(ExtensionContext context, String key) {
		return Optional.ofNullable(getStore(context).get(key, TimeZone.class));
	}

	private static ExtensionContext.Store getStore(ExtensionContext context) {

View on GitHub (pinned to f070c699a0)