redisson/redisson · error · RedisSubscribedConnectionException
Connection already subscribed
Error message
Connection already subscribed
What it means
Redisson's RedissonConnection keeps at most one active RedisSubscription per connection. subscribe(MessageListener, byte[]...) calls checkSubscription(), which throws RedisSubscribedConnectionException when the subscription field is already non-null. This mirrors Redis semantics where a connection entering subscribe mode is dedicated to pub/sub and cannot start a second subscription.
Source
Thrown at redisson-spring/redisson-spring-data/redisson-spring-data-22/src/main/java/org/redisson/spring/data/connection/RedissonConnection.java:1635
return subscription;
}
@Override
public Long publish(byte[] channel, byte[] message) {
return write(channel, StringCodec.INSTANCE, RedisCommands.PUBLISH, channel, message);
}
@Override
public void subscribe(MessageListener listener, byte[]... channels) {
checkSubscription();
subscription = new RedissonSubscription(executorService, listener);
subscription.subscribe(channels);
}
private void checkSubscription() {
if (subscription != null) {
throw new RedisSubscribedConnectionException("Connection already subscribed");
}
if (isQueueing()) {
throw new UnsupportedOperationException("Not supported in queueing mode");
}
if (isPipelined()) {
throw new UnsupportedOperationException("Not supported in pipelined mode");
}
}
@Override
public void pSubscribe(MessageListener listener, byte[]... patterns) {
checkSubscription();
subscription = new RedissonSubscription(executorService, listener);
subscription.pSubscribe(patterns);
}
View on GitHub (pinned to 91188987c2)
Solutions
- Use a fresh connection (RedisConnectionFactory.getConnection()) for each independent subscription instead of reusing the subscribed one.
- Unsubscribe and release the existing subscription before subscribing again on the same connection.
- Let Spring Data Redis' RedisMessageListenerContainer manage subscriptions — it dispatches each listener over dedicated connections.
- Wrap subscribe() in try-catch for RedisSubscribedConnectionException if accidental reuse is possible.
Example fix
// before RedisConnection conn = factory.getConnection(); conn.subscribe(listenerA, "ch1".getBytes()); conn.subscribe(listenerB, "ch2".getBytes()); // throws // after RedisConnection connA = factory.getConnection(); connA.subscribe(listenerA, "ch1".getBytes()); RedisConnection connB = factory.getConnection(); connB.subscribe(listenerB, "ch2".getBytes());
Defensive patterns
Strategy: validation
Validate before calling
// Spring Data Redis does not expose isSubscribed(); track subscriptions yourself or // rely on RedisMessageListenerContainer. If managing manually, keep one connection per subscription: Map<MessageListener, RedisConnection> active = new ConcurrentHashMap<>(); RedisConnection conn = active.computeIfAbsent(listener, k -> factory.getConnection());
Try / catch
try {
conn.subscribe(listener, channel);
} catch (RedisSubscribedConnectionException e) {
// connection already dedicated to pub/sub: open a new one
RedisConnection fresh = factory.getConnection();
fresh.subscribe(listener, channel);
} Prevention
- One subscription per connection — never reuse a subscribed RedissonConnection.
- Prefer RedisMessageListenerContainer for all listener registration.
- In reconnect handlers, create a new connection instead of resubscribing on the old one.
When it happens
Trigger: Calling subscribe() (or pSubscribe(), which shares checkSubscription()) twice on the same RedissonConnection without closing/unsubscribing the first subscription; e.g. two listeners registered through the same RedisTemplate bound to one connection.
Common situations: Registering multiple MessageListener beans through a single RedisConnection; re-subscribing after a reconnect handler runs on the same connection; integration tests that reuse a connection across test cases without unsubscribing.
Related errors
- Connection already subscribed
- Not supported in queueing mode
- Not supported in pipelined mode
- Not supported in queueing mode
- Not supported in pipelined mode
AI-assisted analysis of redisson/redisson@91188987c2 (2026-08-14).
Data as JSON: /api/errors/d14fdeb920a331b3.
Report an issue: GitHub.