{"record":{"id":"e72033bb204b6287","repo":"phalcon/cphalcon","slug":"underlying-exception-message","errorCode":null,"errorMessage":"{underlying exception message}","messagePattern":"\\{underlying exception message\\}","errorType":"exception","errorClass":"Phalcon\\Storage\\Exceptions\\ConnectionFailed","httpStatus":null,"severity":"error","filePath":"phalcon/Storage/Adapter/Redis.zep","lineNumber":444,"sourceCode":"        } else {\n            let method       = \"pconnect\",\n                persistentId = this->options[\"persistentId\"],\n                parameter    = !empty(persistentId) ? persistentId : \"persistentId\" . options[\"index\"];\n        }\n\n        /** @var storage_redis_context $connectionOptions */\n        try {\n            let result = connection->{method}(\n                host,\n                port,\n                timeout,\n                parameter,\n                retryInterval,\n                readTimeout,\n                connectionOptions\n            );\n        } catch \\Exception, ex {\n            throw new ConnectionFailed(ex->getMessage());\n        }\n\n        if !result {\n            throw new ConnectionFailed(\n                sprintf(\n                    \"Could not connect to the Redis server [%s:%s]\",\n                    host,\n                    port\n                )\n            );\n        }\n\n        return this;\n    }\n\n    /**\n     * @throws DatabaseSelectionFailed\n     */","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Storage/Adapter/Redis.zep#L426-L462","documentation":"Redis\\Adapter::checkConnect() wraps the phpredis connect()/pconnect() call in try/catch; any \\Exception (typically RedisException) is rethrown as Phalcon\\Storage\\Exceptions\\ConnectionFailed carrying the underlying message verbatim — e.g. 'Connection refused', 'php_network_getaddresses: getaddrinfo failed' (DNS), 'Connection timed out', or a TLS handshake error from the 'ssl' context options.","triggerScenarios":"redis-server not running or wrong 'port' (connection refused); wrong 'host' hostname (getaddrinfo failed / name resolution); 'timeout' too small for slow networks; 'ssl' options with bad cert paths or peer verification failures; pconnect() on a stale persistent socket.","commonSituations":"Docker/compose where the cache service name is misspelled or the app starts before redis; firewall dropping SYNs so connects time out; TLS misconfiguration when moving to rediss://; IPv6-only DNS in the cluster.","solutions":["Read getMessage(): it is the underlying phpredis error and names the cause","Test reachability from the app container/host: redis-cli -h <host> -p <port> PING","For DNS errors verify resolution: getent hosts <host>","Increase 'timeout' and 'readTimeout' for slow links; fix 'ssl' context options (verify_peer, local_cert paths)","Catch ConnectionFailed at the cache boundary and degrade gracefully (see try-catch pattern)"],"exampleFix":"// before\nnew Redis($factory, ['host' => 'redus']); // typo -> getaddrinfo failed\n\n// after\nnew Redis($factory, ['host' => 'redis', 'port' => 6379]);","handlingStrategy":"retry","validationCode":"// preflight before the first cache call in a request\n$host = $options['host'] ?? '127.0.0.1';\n$port = (int) ($options['port'] ?? 6379);\n$sock = @fsockopen($host, $port, $errno, $errstr, 0.5);\nif ($sock === false) {\n    throw new RuntimeException(\"Redis unreachable at {$host}:{$port}: {$errstr}\");\n}\nfclose($sock);","typeGuard":null,"tryCatchPattern":"// decorate the cache with retry + fallback\n$attempts = 3;\nwhile (true) {\n    try {\n        return $cache->get($key);\n    } catch (\\Phalcon\\Storage\\Exceptions\\ConnectionFailed $e) {\n        // $e->getMessage() is the phpredis error (refused, DNS, timeout)\n        if (--$attempts <= 0) {\n            $logger->error('Redis down: ' . $e->getMessage());\n            return $default; // or rethrow\n        }\n        usleep(250_000 * (4 - $attempts)); // backoff\n    }\n}","preventionTips":["Order container startup so Redis is healthy before the app (depends_on + healthcheck)","Smoke-test DNS and port from the app network in CI, not just from the host","Set 'timeout'/'readTimeout' explicitly instead of relying on 0 defaults under slow networks"],"tags":["php","phalcon","redis","cache","network","connection"],"backgroundTag":"connection-refused","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}