apache/maven · error · DIException
Only String keys are supported for maps: {}
Error message
Only String keys are supported for maps: {} What it means
Thrown by the Sisu bridge when a Map injection is requested whose key type parameter is not String. Legacy Plexus and the Sisu bridge expose component maps keyed by the component's String name (its @Named value or role-hint); arbitrary key types such as Class, enum, or custom objects have no mapping semantics, so the lookup fails fast with DIException.
Source
Thrown at impl/maven-core/src/main/java/org/apache/maven/internal/impl/SisuDiBridgeModule.java:244
List<Binding<?>> list = new ArrayList<>();
// Add DI bindings
list.addAll(getBindings().getOrDefault(elementType, Set.of()));
// Add Plexus bindings
for (var bean : locator.get().locate(toGuiceKey(elementType))) {
if (isPlexusBean(bean)) {
list.add(new BindingToBeanEntry<>(elementType).toBeanEntry(bean));
}
}
//noinspection unchecked
return (Q) list(list.stream().sorted(getPriorityComparator()).toList(), this::getInstance);
};
}
private <Q> Supplier<Q> getMapSupplier(Key<Q> key) {
Key<?> keyType = key.getTypeParameter(0);
Key<Object> valueType = key.getTypeParameter(1);
if (keyType.getRawType() != String.class) {
throw new DIException("Only String keys are supported for maps: " + key);
}
return () -> {
var comparator = getPriorityComparator();
Map<String, Binding<?>> map = new HashMap<>();
for (Binding<?> b : getBindings().getOrDefault(valueType, Set.of())) {
String name =
b.getOriginalKey() != null && b.getOriginalKey().getQualifier() instanceof String s
? s
: "";
map.compute(name, (n, ob) -> ob == null || comparator.compare(ob, b) < 0 ? b : ob);
}
for (var bean : locator.get().locate(toGuiceKey(valueType))) {
if (isPlexusBean(bean)) {
Binding<?> b = new BindingToBeanEntry<>(valueType)
.toBeanEntry(bean)
.prioritize(bean.getRank());
String name = bean.getKey() instanceof com.google.inject.name.Named n ? n.value() : "";
map.compute(name, (n, ob) -> ob == null || ob.getPriority() < b.getPriority() ? b : ob);View on GitHub (pinned to e4093d4e12)
Solutions
- Change the injection to Map<String, T> and convert the String key to your enum/Class where you consume it
- Alternatively inject Set<T> (getAllBindings) and derive the key from each component yourself
- If you truly need typed keys, bind a dedicated registry component that wraps the Map<String, T> internally
- Keep @Named values stable — they become the String keys of the map
Example fix
// before @Inject Map<MyEnum, Handler> handlers; // DIException: only String keys // after @Inject Map<String, Handler> handlers; Handler h = handlers.get(myEnum.name());
Defensive patterns
Strategy: type-guard
Validate before calling
// ensure the injection point signature uses a String key before deployment
Field f = getClass().getDeclaredField("handlers");
if (!Map.class.isAssignableFrom(f.getType()) || !(f.getGenericType() instanceof ParameterizedType pt)
|| pt.getActualTypeArguments()[0] != String.class) {
throw new IllegalStateException("Map injection must be Map<String, ?>");
} Type guard
boolean isSisuCompatibleMap(java.lang.reflect.Type t) {
if (!(t instanceof ParameterizedType pt) || !Map.class.isAssignableFrom((Class<?>) pt.getRawType())) return false;
return pt.getActualTypeArguments()[0] == String.class;
} Prevention
- Standardize on Map<String, T> for injected component maps in Maven extensions
- Convert enum/Class keys at the usage site, not at the injection point
- Document that Sisu maps are keyed by the @Named value of each component
When it happens
Trigger: Declaring an injected field or a lookup like Map<Class<?>, Handler> handlers or Map<MyEnum, Provider<X>>: getMapSupplier() inspects key.getTypeParameter(0) and throws unless it is exactly String.class. Also triggered by refactoring a Map<String, T> field to a different key type while porting Plexus components to JSR-330.
Common situations: Migrating old Plexus @Requirement map injections to javax/jakarta.inject and choosing a 'nicer' key type; writing a new Maven extension that wants a registry keyed by enum; copy-pasting a Guice MapBinder pattern (which supports any key type) into a Sisu environment.
Related errors
- Cannot read metadata from '{}'
- Unable to lookup org.eclipse.aether.RepositorySystem
- No binding to construct an instance for key {}. Existing bi
- Error in component graph of plugin ${plugin.getId()}: ${e.ge
- Unable to load the mojo '${mojoDescriptor.getGoal()}' (or on
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/647a725a45ba57ce.
Report an issue: GitHub.