binarywang/WxJava · warning · IllegalStateException
getAttributeNames: Session already invalidated
Error message
getAttributeNames: Session already invalidated
What it means
StandardSession.getAttributeNames throws IllegalStateException if the session is no longer valid (invalidated or expired). This mirrors servlet-container session semantics: once isValidInternal() is false, any attribute access is forbidden. The session is used internally by message routers (e.g. WxMpMessageRouter) to track per-user state.
Source
Thrown at weixin-java-common/src/main/java/me/chanjar/weixin/common/session/StandardSession.java:95
@Override
public Object getAttribute(String name) {
if (!isValidInternal()) {
throw new IllegalStateException
(SM.getString("sessionImpl.getAttribute.ise"));
}
if (name == null) {
return null;
}
return this.attributes.get(name);
}
@Override
public Enumeration<String> getAttributeNames() {
if (!isValidInternal()) {
throw new IllegalStateException(SM.getString("sessionImpl.getAttributeNames.ise"));
}
Set<String> names = new HashSet<>();
names.addAll(this.attributes.keySet());
return Collections.enumeration(names);
}
@Override
public void setAttribute(String name, Object value) {
// Name cannot be null
if (name == null) {
throw new IllegalArgumentException(SM.getString("sessionImpl.setAttribute.namenull"));
}
// Null value is the same as removeAttribute()
if (value == null) {
removeAttribute(name);
return;View on GitHub (pinned to 1c43293a3c)
Solutions
- Call session.isValid() (or the router's validity check) before reading attributes.
- Discard session references after invalidate() and re-acquire a fresh session from the manager.
- Tune maxInactiveInterval to match your handler's lifetime if timeouts happen mid-flow.
- Catch IllegalStateException around post-invalidate cleanup and treat it as 'no attributes'.
Example fix
// before
Enumeration<String> names = session.getAttributeNames(); // throws if expired
// after
if (session.isValid()) {
Enumeration<String> names = session.getAttributeNames();
} else {
names = Collections.emptyEnumeration();
} Defensive patterns
Strategy: validation
Validate before calling
if (session.isValid()) {
Enumeration<String> names = session.getAttributeNames();
} else {
names = Collections.emptyEnumeration();
} Type guard
private static boolean sessionAccessible(WxSession s) {
return s != null && s.isValid();
} Try / catch
try {
return session.getAttributeNames();
} catch (IllegalStateException e) {
// session expired/invalidated — treat as empty
return Collections.emptyEnumeration();
} Prevention
- Check session.isValid() before any attribute read after a gap.
- Do not retain WxSession references across long async work; re-acquire from the manager.
- Tune maxInactiveInterval to your handler's expected lifetime.
When it happens
Trigger: Calling session.getAttributeNames() after session.invalidate() was called, or after the session expired past its maxInactiveInterval.
Common situations: A message-router handler retains a WxSession reference and reads attributes after the session timed out; explicit invalidate() followed by a cleanup/access pass; long-lived async work holding a stale session.
Related errors
- setAttribute: Session [{0}] has already been invalidated
- invalidate: Session already invalidated
- createSession: Too many active sessions
- setAttribute: name parameter cannot be null
AI-assisted analysis of binarywang/WxJava@1c43293a3c (2026-08-14).
Data as JSON: /api/errors/f9126491d42a75b9.
Report an issue: GitHub.