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

  1. Discard the connection object — it is marked broken and returned to the pool as unusable; obtain a fresh connection from the pool.
  2. Audit for concurrent use or manual close() of Connection objects from multiple threads.
  3. Check for aggressive firewalls/LB idle timeouts killing the socket between commands.
  4. 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

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.

Related errors


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)