redis/jedis · error · JedisException
is not connected to a Connection.
Error message
<class> is not connected to a Connection.
What it means
JedisSafeAuthenticator.sendAndFlushCommand() needs an underlying Connection to send the AUTH/token-refresh command. If the internal client reference is null, no connection is attached, so it throws JedisException(getClass() + " is not connected to a Connection."). This happens inside safeReAuthenticate, i.e. while trying to transparently re-authenticate the connection.
Solutions
- Ensure the connection stays open for the lifetime of the authenticator; check for premature close()/disconnect calls.
- Verify token-refresh lifecycle: don't close connections while safeReAuthenticate may be in flight.
- Upgrade Jedis — newer versions harden the re-auth path against this race.
- Recreate the client/connection after this error; the authenticator state is unusable.
Example fix
// before
connection.close(); // then token expires
// safeReAuthenticate -> JedisException: not connected
// after
try {
// keep connection open until re-auth completes
connection.ping();
} catch (JedisConnectionException e) {
client.renewConnection(); // rebuild before token refresh is needed
} Defensive patterns
Strategy: try-catch
Validate before calling
if (connection == null || !connection.isConnected()) { /* rebuild connection before token ops */ } Type guard
boolean authenticatorReady(JedisSafeAuthenticator a) { return a != null && a.isConnected(); } Try / catch
try {
client.safeAuth();
} catch (JedisException e) {
if (e.getMessage().contains("is not connected to a Connection")) {
client.rebuildConnection(); // recreate and re-authenticate
} else throw e;
} Prevention
- Don't close connections while token-based re-authentication may be pending.
- Check connection liveness (ping) before long-lived background token operations.
- Upgrade to a Jedis version with hardened re-auth lifecycle handling.
- Avoid sharing the authenticated client across threads that may close it independently.
When it happens
Trigger: safeReAuthenticate() triggering sendAndFlushCommand() when the authenticator's client field is null — the authenticator was created but never wired to a live Connection, or the connection was closed/nulled before token refresh ran.
Common situations: Using token-based authentication (IAM/SToken) with a connection that was closed concurrently; a race where re-auth fires after connection teardown; misconfigured client construction where the authenticator is instantiated without a connection.
Related errors
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/5947c84144aa0ca4.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/JedisSafeAuthenticator.java:35
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.jedis.util.SafeEncoder;
class JedisSafeAuthenticator {
private static final Token PLACEHOLDER_TOKEN = new SimpleToken(null, null, 0, 0, null);
private static final Logger logger = LoggerFactory.getLogger(JedisSafeAuthenticator.class);
protected volatile Connection client;
protected final Consumer<Object> authResultHandler = this::processAuthReply;
protected final Consumer<Token> authenticationHandler = this::safeReAuthenticate;
protected final AtomicReference<Token> pendingTokenRef = new AtomicReference<Token>(null);
protected final ReentrantLock commandSync = new ReentrantLock();
protected final Queue<Consumer<Object>> resultHandler = new ConcurrentLinkedQueue<Consumer<Object>>();
protected void sendAndFlushCommand(Command command, Object... args) {
if (client == null) {
throw new JedisException(getClass() + " is not connected to a Connection.");
}
CommandArguments cargs = new CommandArguments(command).addObjects(args);
Token newToken = pendingTokenRef.getAndSet(PLACEHOLDER_TOKEN);
// lets send the command without locking !!IF!! we know that pendingTokenRef is null replaced with PLACEHOLDER_TOKEN and no re-auth will go into action
// !!ELSE!! we are locking since we already know a re-auth is still in progress in another thread and we need to wait for it to complete, we do nothing but wait on it!
if (newToken != null) {
commandSync.lock();
}
try {
client.sendCommand(cargs);
client.flush();
} finally {
Token newerToken = pendingTokenRef.getAndSet(null);
// lets check if a newer token received since the beginning of this sendAndFlushCommand call
if (newerToken != null && newerToken != PLACEHOLDER_TOKEN) {
safeReAuthenticate(newerToken);View on GitHub (pinned to 6dac31d4c2)