junit-team/junit5 · error · NamespacedHierarchicalStoreException

Object stored under key

Error message

Object stored under key [%s] is not of required type [%s], but was [%s]: %s

What it means

NamespacedHierarchicalStore.get(key, requiredType) throws when the stored value is not assignable to the requested type. The store is type-erased internally; the caller asks for a Class<T> and the implementation checks isAssignableTo(value, requiredType). The message reports the key, the requested type, the actual type, and the value.

Solutions

  1. Inspect the message: it gives the actual stored class - update the requested type to match, or change what is stored.
  2. Use a unique key per extension/value to avoid collisions (e.g. include the extension class or a constant owned by the extension).
  3. If the value type legitimately changed, clear the old store entry or use a new Namespace/key pair.
  4. Verify getOrComputeIfAbsent's supplier returns the same type you later request.

Example fix

// before
store.put(Namespace.GLOBAL, "cfg", 42);          // Integer
String s = store.get(Namespace.GLOBAL, "cfg", String.class); // throws
// after
Integer i = store.get(Namespace.GLOBAL, "cfg", Integer.class);
Defensive patterns

Strategy: type-guard

Validate before calling

// Check the stored type before requesting it
Object raw = store.get(namespace, key, Object.class);
if (raw != null && !requiredType.isInstance(raw)) {
    throw new IllegalStateException("stored type is " + raw.getClass());
}
T value = store.get(namespace, key, requiredType);

Type guard

static <T> boolean storeHasType(NamespacedHierarchicalStore s, Namespace n, Object k, Class<T> t) {
    Object v = s.get(n, k, Object.class);
    return v == null || t.isInstance(v);
}

Try / catch

try {
    return store.get(namespace, key, requiredType);
} catch (NamespacedHierarchicalStoreException e) {
    // wrong type: read message, migrate the key, or use a new key
}

Prevention

When it happens

Trigger: Calling store.get(namespace, key, SomeType.class) where the value previously stored under (namespace, key) via put/getOrComputeIfAbsent is of a different type. Common when an ExtensionContext / EngineContext store key is reused across extensions with different value types, or when the stored type changed between versions.

Common situations: Two extensions store different value types under the same Namespace+key; a version upgrade changed the stored value class; a test reads a value with the wrong Class token after a refactor; misuse of getOrComputeIfAbsent where the supplier returns an incompatible type.

Related errors


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

Appendix: source

Thrown at junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStore.java:493

	private <T> @Nullable T castToRequiredType(Object key, @Nullable Object value, Class<T> requiredType) {
		Preconditions.notNull(requiredType, "requiredType must not be null");
		if (value == null) {
			return null;
		}
		return castNonNullToRequiredType(key, value, requiredType);
	}

	@SuppressWarnings("unchecked")
	private <T, V> T castNonNullToRequiredType(Object key, V value, Class<T> requiredType) {
		if (isAssignableTo(value, requiredType)) {
			if (requiredType.isPrimitive()) {
				return (T) requireNonNull(getWrapperType(requiredType)).cast(value);
			}
			return requiredType.cast(value);
		}
		// else
		throw new NamespacedHierarchicalStoreException(
			"Object stored under key [%s] is not of required type [%s], but was [%s]: %s".formatted(key,
				requiredType.getName(), value.getClass().getName(), value));
	}

	private void rejectIfClosed() {
		if (this.closed) {
			throw new NamespacedHierarchicalStoreException(
				"A NamespacedHierarchicalStore cannot be modified or queried after it has been closed");
		}
	}

	private record CompositeKey<N>(N namespace, Object key) {

		CompositeKey {
			Preconditions.notNull(namespace, "namespace must not be null");
			Preconditions.notNull(key, "key must not be null");
		}

View on GitHub (pinned to f070c699a0)