Understanding the Exception
When integrating Java applications with Redis via the Jedis client, developers may encounter the following runtime exception:
redis.clients.jedis.exceptions.JedisDataException: ERR Client sent AUTH, but no password is set
This error indicates a mismatch in security expectations between the client and the server. Specificallly, the Java application explicitly sends a AUTH command to authenticate, but the target Redis instance has not been configured with a password requirement.
Root Cause Analysis
The Redis protocol strictly validates authentication commands against the server's requirepass directive. The exception is triggered when:
- The Redis instance is running in its default, unsecured state (no password configured).
- The Jedis client is programmed or configured to call the
auth()method immediately upon connection. - Environment-specific configuration files inadvertently enforce authentication in development or staging environments where it is disabled.
Resolution Strategies
Addressing this issue depends entirely on whether the Redis deployment is intended to be secured. Below are two implementation paths.
Path 1: Connecting to an Unsecured Instance
If the Redis server is deployed locally or in a restricted network without authentication, remove any explicit credential passing from the connection logic.
import redis.clients.jedis.Jedis;
public class UnsecuredRedisClient {
public static void executeOperation() {
// Instantiate connection to the default port
try (Jedis connection = new Jedis("127.0.0.1", 6379)) {
// Directly interact without authentication
connection.set("session_token", "abc-123-def");
String retrievedData = connection.get("session_token");
System.out.println("Retrieved: " + retrievedData);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Note the use of try-with-resources to guarantee proper socket closure, eliminating the risk of connection leaks.
Path 2: Connecting to a Password-Protected Instance
For production environments, Redis must enforce authentication via the requirepass directive in redis.conf. The client code must then supply the exact matching credential.
import redis.clients.jedis.Jedis;
public class SecuredRedisClient {
private static final String HOST = "redis.prod.internal";
private static final int PORT = 6379;
private static final String CREDENTIALS = System.getenv("REDIS_SECRET");
public static void main(String[] args) {
if (CREDENTIALS == null || CREDENTIALS.isEmpty()) {
throw new IllegalStateException("Missing authentication token for Redis");
}
try (Jedis connection = new Jedis(HOST, PORT)) {
connection.auth(CREDENTIALS);
connection.ping();
// Proceed with data operations
connection.set("cache:config:v1", "{\"theme\": \"dark\"}");
System.out.println("Cache update successful.");
}
}
}
Configuration Alignment Checklist
Prevent future mismatches by adhering to these operational guidelines:
- Server Directive: Verify
requirepassinredis.conf. A commented-out or absent line means authentication is disabled. - Client-Side Logic: Conditionally trigger the
auth()method based on configuration flags. Hardcoding authentication calls is unsafe for flexible deployments. - Network Exposure: Never expose an unauthenticated Redis port to public networks. Bind to
127.0.0.1or use firewall rules if authentication is intentionally disabled for testing. - Environment Variables: Store credentials outside the source code. Inject them via environment variables or secret managers to avoid configuration drift between local and production environments.