redis/jedis · error · JedisConnectionException
Failed to set SO_TIMEOUT
Error message
Failed to set SO_TIMEOUT
What it means
Connection.applyCurrentTimeout sets the socket's SO_TIMEOUT to match the connection's current timeout. If the underlying socket refuses (SocketException), the connection is marked broken and a JedisConnectionException is thrown. This typically means the socket has been closed or is otherwise unusable at the OS level.
Solutions
- Discard the connection object — it is marked broken and returned to the pool as unusable; obtain a fresh connection from the pool.
- Audit for concurrent use or manual close() of Connection objects from multiple threads.
- Check for aggressive firewalls/LB idle timeouts killing the socket between commands.
- If using timeouts around blocking commands, wrap in retry logic that reconnects on JedisConnectionException.
Defensive patterns
Strategy: try-catch
Validate before calling
// guard timeout changes to live, thread-owned connections only
if (connection != null && !isClosed(connection)) {
connection.setSoTimeout(ms);
} Try / catch
try {
connection.setTimeoutInfinite();
// blocking command
} catch (JedisConnectionException e) {
connection = pool.getResource(); // socket was dead; take a fresh one
} Prevention
- Never share a Connection across threads
- Don't mutate timeouts on connections you didn't open
- Tune pool eviction so dead sockets are replaced early
- Investigate idle-kill behavior of firewalls/LBs between client and Redis
When it happens
Trigger: Calling setTimeoutInfinite/rollbackTimeout/setSoTimeout, or any command path that re-applies the timeout (connect, readProtocolWithCheckingBroken, readPushesWithCheckingBroken) when the socket is already closed, reset by a peer, or set after socket close on a broken connection.
Common situations: A server or middlebox closed the TCP connection and the client later tries to change the timeout; sharing a Connection across threads where one closed it; socket closed during failover; calling timeout APIs after explicitly closing the connection.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Failed to create socket.
- Failed to check buffer on connection.
- null is not a valid argument.
- HashImport ' ' has been discarded
- HashImport ' ' expects values but got
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/2087fbeee1505d13.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/Connection.java:415
*/
public void setSoTimeout(int millis) {
defaultTimeoutSource.setDefaults(millis, defaultTimeoutSource.getDefaults().blockingTimeout);
applyCurrentTimeout();
}
private int currentTimeout() {
return isBlocking ? defaultTimeoutSource.get().blockingTimeout : defaultTimeoutSource.get().timeout;
}
void applyCurrentTimeout() {
int timeout = currentTimeout();
if (timeout == appliedSoTimeout || socket == null) {
return;
}
try {
socket.setSoTimeout(timeout);
} catch (SocketException e) {
throw markBroken(new JedisConnectionException("Failed to set SO_TIMEOUT", e));
}
appliedSoTimeout = timeout;
if (logger.isTraceEnabled()) {
logger.trace("Timeout applied millis={} blocking={} conn={}", timeout, isBlocking,
toIdentityString());
}
}
/**
* Sets the socket read timeout (SO_TIMEOUT) to infinite for blocking commands.
*
* <p>The effective timeout applied depends on the current connection state:</p>
* <ul>
* <li>If relaxed timeout mode is active, the looser of the configured blocking timeout and
* the relaxed blocking timeout is used, {@code 0} (infinite) being the loosest.</li>
* <li>Otherwise, the configured blocking timeout is applied.</li>
* </ul>
*View on GitHub (pinned to 6dac31d4c2)