redis/jedis · error · IllegalStateException
setHostAndPort method has limited capability.
Error message
setHostAndPort method has limited capability.
What it means
JedisFactory.setHostAndPort can only retarget the connection's socket factory if it is a DefaultJedisSocketFactory, which supports in-place host/port updates. When a custom JedisSocketFactory implementation (or a factory type that does not implement updateHostAndPort) was supplied, the client cannot be re-pointed at a new cluster node, so this IllegalStateException is thrown to fail fast instead of silently connecting to the wrong host. It is thrown inside JedisFactory.setHostAndPort (JedisFactory.java:177).
Solutions
- Extend DefaultJedisSocketFactory instead of implementing JedisSocketFactory directly, so updateHostAndPort is supported.
- If a fully custom socket factory is required, create a new JedisFactory (new pool) for each host instead of calling setHostAndPort.
- Wrap the call and on this error rebuild the pool/factory pointed at the new HostAndPort.
Example fix
// before JedisFactory f = new JedisFactory(hostAndPort, clientConfig); f.setJedisSocketFactory(new MyCustomSocketFactory(cfg)); f.setHostAndPort(newHostAndPort); // throws IllegalStateException // after JedisFactory f = new JedisFactory(newHostAndPort, clientConfig); // use DefaultJedisSocketFactory (default) // or extend DefaultJedisSocketFactory in MyCustomSocketFactory so updateHostAndPort works f.setHostAndPort(newHostAndPort);
Defensive patterns
Strategy: try-catch
Validate before calling
if (!(factory.getJedisSocketFactory() instanceof DefaultJedisSocketFactory)) {
// rebuild factory/pool instead of calling setHostAndPort
} Type guard
boolean supportsHostUpdate(JedisFactory f) {
return f.getJedisSocketFactory() instanceof DefaultJedisSocketFactory;
} Try / catch
try {
factory.setHostAndPort(newHostAndPort);
} catch (IllegalStateException e) {
// recreate JedisFactory/pool for newHostAndPort
pool = rebuildPool(newHostAndPort, clientConfig);
} Prevention
- Extend DefaultJedisSocketFactory rather than implementing JedisSocketFactory from scratch when customizing sockets.
- Test cluster/sentinel failover paths whenever a custom socket factory is introduced.
- Prefer configuring host/port through clientConfig builders instead of mutating factories at runtime.
When it happens
Trigger: Calling setHostAndPort on a JedisFactory (directly, or indirectly via JedisCluster topology refresh / JedisSentinelPool master switch) when the factory was constructed with a custom JedisSocketFactory that is not an instance of DefaultJedisSocketFactory.
Common situations: Users injecting a custom socket factory (e.g. for TLS wrappers, proxies, or custom DNS resolution) into JedisPool/JedisCluster config, then the cluster client attempts a MOVED/ASK redirect or sentinel failover and tries to update the target host.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- HashImport ' ' has been discarded
- Cannot use Jedis when in Multi. Please use Transaction or…
- Cannot use Jedis when in Pipeline. Please use Pipeline or…
- Blocking pub/sub operations are not supported on…
- Unknown message type
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/2037c86fc2294106.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/JedisFactory.java:177
final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) {
if (!JedisURIHelper.isValid(uri)) {
throw new InvalidURIException(
String.format("Cannot open Redis connection due invalid URI. %s", uri.toString()));
}
this.clientConfig = legacyConfigBuilderWithoutProtocolNegotiation().connectionTimeoutMillis(connectionTimeout)
.socketTimeoutMillis(soTimeout).blockingSocketTimeoutMillis(infiniteSoTimeout)
.user(JedisURIHelper.getUser(uri)).password(JedisURIHelper.getPassword(uri))
.database(JedisURIHelper.getDBIndex(uri)).clientName(clientName)
.protocol(JedisURIHelper.getRedisProtocol(uri)).ssl(JedisURIHelper.isRedisSSLScheme(uri))
.sslSocketFactory(sslSocketFactory).sslParameters(sslParameters)
.hostnameVerifier(hostnameVerifier).build();
this.jedisSocketFactory = new DefaultJedisSocketFactory(
new HostAndPort(uri.getHost(), uri.getPort()), this.clientConfig);
}
void setHostAndPort(final HostAndPort hostAndPort) {
if (!(jedisSocketFactory instanceof DefaultJedisSocketFactory)) {
throw new IllegalStateException("setHostAndPort method has limited capability.");
}
((DefaultJedisSocketFactory) jedisSocketFactory).updateHostAndPort(hostAndPort);
}
@Override
public void activateObject(PooledObject<Jedis> pooledJedis) throws Exception {
final Jedis jedis = pooledJedis.getObject();
if (jedis.getDB() != clientConfig.getDatabase()) {
jedis.select(clientConfig.getDatabase());
}
}
@Override
public void destroyObject(PooledObject<Jedis> pooledJedis) throws Exception {
final Jedis jedis = pooledJedis.getObject();
if (jedis.isConnected()) {
try {
jedis.close();View on GitHub (pinned to 6dac31d4c2)