{"record":{"id":"c894122a80bdf08a","repo":"getgrav/grav","slug":"redis-authentication-failed","errorCode":null,"errorMessage":"Redis authentication failed","messagePattern":"Redis authentication failed","errorType":"exception","errorClass":"RedisException","httpStatus":null,"severity":"warning","filePath":"system/src/Grav/Common/Cache.php","lineNumber":395,"sourceCode":"                if (extension_loaded('redis')) {\n                    $redis = new \\Redis();\n                    try {\n                        $socket = $this->config->get('system.cache.redis.socket', false);\n                        $password = $this->config->get('system.cache.redis.password', false);\n                        $databaseId = $this->config->get('system.cache.redis.database', 0);\n\n                        if ($socket) {\n                            $redis->connect($socket);\n                        } else {\n                            $redis->connect(\n                                $this->config->get('system.cache.redis.server', 'localhost'),\n                                $this->config->get('system.cache.redis.port', 6379)\n                            );\n                        }\n\n                        // Authenticate with password if set\n                        if ($password && !$redis->auth($password)) {\n                            throw new \\RedisException('Redis authentication failed');\n                        }\n\n                        // Select alternate ( !=0 ) database ID if set\n                        if ($databaseId && !$redis->select($databaseId)) {\n                            throw new \\RedisException('Could not select alternate Redis database ID');\n                        }\n\n                        $adapter = new RedisAdapter($redis, $namespace, $defaultLifetime);\n                        $resolved_driver_name = 'redis';\n                    } catch (Throwable $e) {\n                        $this->logCacheFallback($driver_name, 'file', $e->getMessage());\n                        $adapter = $this->createFilesystemAdapter($namespace, $defaultLifetime);\n                        $resolved_driver_name = 'file';\n                    }\n                } else {\n                    $this->logCacheFallback($driver_name, 'file', 'Redis extension not installed');\n                    $adapter = $this->createFilesystemAdapter($namespace, $defaultLifetime);\n                    $resolved_driver_name = 'file';","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Common/Cache.php#L377-L413","documentation":"While building the Redis cache adapter, Grav connects with the configured socket or server and then calls phpredis auth() when system.cache.redis.password is truthy. If Redis rejects the credentials and auth() returns false, Grav throws RedisException. The surrounding catch records the reason and falls back to the filesystem cache, so pages usually keep working but without Redis.","triggerScenarios":"Set system.cache.redis.driver to redis with the redis extension loaded and a non-empty system.cache.redis.password, then supply a wrong password, a password for the wrong Redis user, or credentials from a stale environment. The failed auth at Cache.php:394-396 triggers the fallback at Cache.php:405-409.","commonSituations":"Password rotation, an unquoted YAML value that parses differently, a Redis 6 ACL named user while this code path sends only a password, environment-specific credentials, or a proxy/managed Redis that requires a different authentication mechanism.","solutions":["Verify the exact credentials from the same host with redis-cli -h HOST -p PORT -a 'PASSWORD' PING (or the configured socket) and correct user/config/system.yaml.","Use the password for Redis's default user or patch the authentication call to use the phpredis username/password form; the current Grav code passes only a password.","Quote the YAML password when it contains special characters, and clear Grav's cached configuration after changing it.","Restart PHP/FPM and the web server so the updated configuration and environment are used.","Inspect the fallback log entry; if Redis is optional, size the filesystem cache for the resulting load instead of leaving repeated auth failures."],"exampleFix":"# before (user/config/system.yaml)\ncache:\n  driver: redis\n  redis:\n    server: 127.0.0.1\n    port: 6379\n    password: old-password\n\n# after\ncache:\n  driver: redis\n  redis:\n    server: 127.0.0.1\n    port: 6379\n    password: 'correct-password'","handlingStrategy":"validation","validationCode":"$redis = new Redis();\n$connected = $socket ? $redis->connect($socket) : $redis->connect($host, $port);\nif (!$connected || ($password && !$redis->auth($password))) {\n    throw new RuntimeException('Redis credentials rejected; fix system.cache.redis.password.');\n}\n$redis->close();","typeGuard":null,"tryCatchPattern":"try {\n    $cache = new RedisAdapter($redis, $namespace, $lifetime);\n} catch (RedisException $e) {\n    error_log('Redis unavailable; using filesystem cache: ' . $e->getMessage());\n    $cache = new FilesystemAdapter($namespace, $lifetime, $cacheDir);\n}","preventionTips":["Run an AUTH plus PING health check before enabling Redis in production.","Keep Redis credentials in environment-specific configuration and rotate deliberately.","Quote YAML passwords containing punctuation.","Watch Grav cache-fallback logs during deployment.","Remember this Grav path sends a password only, not a Redis ACL username."],"tags":["grav","cache","redis","authentication","phpredis","fallback"],"backgroundTag":"redis-auth-failed","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}