junit-team/junit5 · error · ExtensionContextException

%s

Error message

%s

What it means

A generic wrapper thrown by NamespaceAwareStore.accessStore: any operation on the ExtensionContext.Store (get, put, getOrComputeIfAbsent, remove, computeIfAbsent, etc.) that fails inside the underlying NamespacedHierarchicalStore with a NamespacedHierarchicalStoreException is rethrown as an ExtensionContextException carrying the same message. The '%s' message is whatever the store layer produced (type mismatch, null key, etc.).

Source

Thrown at junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java:123

		Preconditions.notNull(key, "key must not be null");
		Supplier<@Nullable Object> action = () -> this.valuesStore.remove(this.namespace, key);
		return this.<@Nullable Object> accessStore(action);
	}

	@Override
	public <T> @Nullable T remove(Object key, Class<T> requiredType) {
		Preconditions.notNull(key, "key must not be null");
		Preconditions.notNull(requiredType, "requiredType must not be null");
		Supplier<@Nullable T> action = () -> this.valuesStore.remove(this.namespace, key, requiredType);
		return this.<@Nullable T> accessStore(action);
	}

	private <T extends @Nullable Object> T accessStore(Supplier<T> action) {
		try {
			return action.get();
		}
		catch (NamespacedHierarchicalStoreException e) {
			throw new ExtensionContextException(e.getMessage(), e);
		}
	}

}

View on GitHub (pinned to f070c699a0)

Solutions

  1. Inspect the wrapped NamespacedHierarchicalStoreException message - it states the actual constraint violated.
  2. Use a consistent type per (namespace, key) pair across all extensions sharing the namespace.
  3. Avoid sharing mutable stored objects across parallel test threads without external synchronization.

Example fix

// before
store.put("cfg", List.of("a"));
Map<String,String> cfg = store.get("cfg", Map.class); // type mismatch -> wrapped
// after
store.put("cfg", Map.of("k","v"));
Map<String,String> cfg = store.get("cfg", Map.class);
Defensive patterns

Strategy: try-catch

Validate before calling

Object stored = store.get(key);
Class<?> expected = Map.class;
if (stored != null && !expected.isInstance(stored)) {
    throw new IllegalStateException("Stored " + stored.getClass() + " is not " + expected);
}

Type guard

Object v = store.get("cfg");
if (!(v instanceof Map<?,?> m)) {
    throw new IllegalStateException("expected Map, got " + (v == null ? "null" : v.getClass()));
}

Try / catch

try {
    Map<String,String> cfg = store.get("cfg", Map.class);
} catch (ExtensionContextException e) {
    log.error("store access failed: {}", e.getCause());
    throw e;
}

Prevention

When it happens

Trigger: Any Store.<operation> where the underlying store throws - e.g. get(key, requiredType) with a stored value that is not assignable to requiredType, or computeIfAbsent racing on a null defaultCreator result. accessStore catches NamespacedHierarchicalStoreException and wraps it.

Common situations: Storing mixed types under the same key and later fetching with the wrong requiredType; one extension stores a List and another fetches with Map.class; concurrent modification of the store from parallel test threads when the store is not thread-safe for the operation.

Related errors


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