apache/maven · error · DIException
Cannot rebind scope annotation class to a different…
Error message
Cannot rebind scope annotation class to a different implementation: {} What it means
bindScope associates a scope annotation (Singleton, per-lookup, custom) with its Scope implementation. Scopes live in a map keyed by annotation class; if the annotation was already registered, scopes.put returns the previous entry and the injector throws DIException. Despite the message saying 'different implementation', any second bindScope for the same annotation fails.
Solutions
- Locate the duplicate: the message names the annotation class — search every bindScope call for it
- Bind each scope annotation exactly once per injector and centralize scope setup in one bootstrap place
- Create a fresh injector per application or test instead of re-configuring a shared one
Example fix
// before
injector.bindScope(Singleton.class, singletonScope); // second registration -> DIException
// after
Set<Class<? extends Annotation>> registered = new HashSet<>();
if (registered.add(Singleton.class)) {
injector.bindScope(Singleton.class, singletonScope);
} Defensive patterns
Strategy: validation
Validate before calling
private final Set<Class<? extends Annotation>> boundScopes = new HashSet<>();
void bindScopeOnce(Injector injector, Class<? extends Annotation> anno, Scope scope) {
if (boundScopes.add(anno)) {
injector.bindScope(anno, scope);
}
} Try / catch
try {
injector.bindScope(Singleton.class, scope);
} catch (DIException e) {
// annotation already registered: skip or reuse the existing scope registration
log.debug("scope already bound: {}", e.getMessage());
} Prevention
- Centralize bindScope calls in a single bootstrap class
- Use a fresh injector per context rather than mutating a long-lived one
When it happens
Trigger: Two bindScope calls with the same annotation class on one injector — e.g. two extensions or bootstrap modules each registering @Singleton, or re-running configuration against a shared injector.
Common situations: Adding a custom scope that a core module already binds; plexus-to-DI migrations double-registering scopes; tests that reuse a global injector across different configurations.
Related errors
- Cannot access outside of a scoping block
- Cannot access session scope outside of a scoping block
- No instance of is bound to the session scope.
- No instance of is bound to the mojo execution scope.
- The Typed annotation must contain only interfaces but the…
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/759cc7d1f6556652.
Report an issue: GitHub.
Appendix: source
Thrown at impl/maven-di/src/main/java/org/apache/maven/di/impl/InjectorImpl.java:129
}
}
} catch (Exception e) {
throw new DIException("Error while discovering DI classes from classLoader", e);
}
return this;
}
@Nonnull
@Override
public Injector bindScope(@Nonnull Class<? extends Annotation> scopeAnnotation, @Nonnull Scope scope) {
return bindScope(scopeAnnotation, () -> scope);
}
@Nonnull
@Override
public Injector bindScope(@Nonnull Class<? extends Annotation> scopeAnnotation, @Nonnull Supplier<Scope> scope) {
if (scopes.put(scopeAnnotation, scope) != null) {
throw new DIException(
"Cannot rebind scope annotation class to a different implementation: " + scopeAnnotation);
}
return this;
}
@Nonnull
@Override
public <U> Injector bindInstance(@Nonnull Class<U> clazz, @Nonnull U instance) {
Key<?> key = Key.of(clazz, ReflectionUtils.qualifierOf(clazz));
Binding<U> binding = Binding.toInstance(instance);
return doBind(key, binding);
}
@Override
public <U> Injector bindSupplier(@Nonnull Class<U> clazz, @Nonnull Supplier<U> supplier) {
Key<?> key = Key.of(clazz, ReflectionUtils.qualifierOf(clazz));
Binding<U> binding = Binding.toSupplier(supplier);
return doBind(key, binding);View on GitHub (pinned to e4093d4e12)