apache/maven · error · IllegalStateException
A maven session is already associated with the repository se
Error message
A maven session is already associated with the repository session
What it means
InternalSession.associate stores the Maven Session inside the RepositorySystemSession's data map using set-if-absent semantics (rsession.getData().set(InternalSession.class, null, ...)). If a binding is already present the call returns false and IllegalStateException is thrown: one repository session can carry at most one Maven session.
Source
Thrown at impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java:64
import static org.apache.maven.impl.ImplUtils.cast;
public interface InternalSession extends Session {
static InternalSession from(Session session) {
if (session instanceof InternalSession is) {
return is;
}
return cast(InternalSession.class, session, "session should be an " + InternalSession.class);
}
static InternalSession from(org.eclipse.aether.RepositorySystemSession session) {
return cast(InternalSession.class, session.getData().get(InternalSession.class), "session");
}
static void associate(org.eclipse.aether.RepositorySystemSession rsession, Session session) {
if (!rsession.getData().set(InternalSession.class, null, from(session))) {
throw new IllegalStateException("A maven session is already associated with the repository session");
}
}
/**
* Executes and optionally caches a request using the provided supplier function. If caching is enabled
* for this session, the result will be cached and subsequent identical requests will return the cached
* value without re-executing the supplier.
*
* @param <REQ> The request type
* @param <REP> The response type
* @param req The request object used as the cache key
* @param supplier The function to execute and cache the result
* @return The result from the supplier (either fresh or cached)
* @throws RuntimeException Any exception thrown by the supplier will be cached and re-thrown on subsequent calls
*/
<REQ extends Request<?>, REP extends Result<REQ>> REP request(REQ req, Function<REQ, REP> supplier);
<REQ extends Request<?>, REP extends Result<REQ>> List<REP> requests(View on GitHub (pinned to e4093d4e12)
Solutions
- Create a fresh RepositorySystemSession (or a copy via new DefaultRepositorySystemSession(existing) with its own session data) for every Maven session you associate
- Associate exactly once, at bootstrap, and reuse the associated Maven session afterwards
- Check rsession.getData().get(InternalSession.class) before associating if the session's history is unknown
Example fix
// before: one shared repo session, associated per build
for (Build b : builds) {
InternalSession.associate(sharedRepoSession, mavenSessionFor(b)); // IllegalStateException on 2nd pass
}
// after: fresh repo session data per build
for (Build b : builds) {
DefaultRepositorySystemSession rss = new DefaultRepositorySystemSession(sharedRepoSession);
InternalSession.associate(rss, mavenSessionFor(b));
} Defensive patterns
Strategy: validation
Validate before calling
// associate only when the repository session has no binding yet
if (rsession.getData().get(InternalSession.class) != null) {
// already associated: reuse it or start from a fresh session copy
rsession = new DefaultRepositorySystemSession(rsession); // new data map
}
InternalSession.associate(rsession, mavenSession); Try / catch
try {
InternalSession.associate(rsession, session);
} catch (IllegalStateException e) {
// repository session already carries a Maven session: create detached session data and retry
DefaultRepositorySystemSession fresh = new DefaultRepositorySystemSession(rsession);
InternalSession.associate(fresh, session);
rsession = fresh;
} Prevention
- Give each Maven session its own RepositorySystemSession (or a copy with fresh session data)
- Associate exactly once at bootstrap and pass the pair around together
- In long-lived embedders, audit for shared/singleton repository sessions before re-entry
When it happens
Trigger: Calling associate(repositorySession, mavenSession) twice with the same repository session; in embedded setups, creating a new Maven Session per build while reusing a shared/singleton RepositorySystemSession.
Common situations: IDE integrations and test harnesses that repeatedly bootstrap Maven against one long-lived repository session; frameworks wrapping Maven executions in loops without resetting session state.
Related errors
- {} is null
- {} is not an instance of {}
- Unable to lookup org.eclipse.aether.RepositorySystem
- Not yet implemented
- Error evaluating plugin parameter expression: ${expression}
AI-assisted analysis of apache/maven@e4093d4e12 (2026-08-21).
Data as JSON: /api/errors/487b5156c2d50265.
Report an issue: GitHub.