symfony/symfony · error · InvalidArgumentException

Invalid Redis DSN.

Error message

Invalid Redis DSN.

What it means

Thrown by RedisAdapter::createConnection() when parse_url() fails on the normalised DSN, returning false. Before parsing, the method rewrites the scheme to 'file:' and extracts auth credentials via preg_replace_callback; if the resulting string is not a parseable URL, parse_url returns false and the DSN is deemed invalid. This is a catch-all for malformed DSNs that passed the scheme check but are structurally broken.

Solutions

  1. Provide a complete, well-formed DSN: 'redis://host:6379' or 'redis:///var/run/redis.sock'.
  2. Percent-encode any special characters in the username/password portion of the DSN.
  3. Check the environment variable is fully populated (not truncated).
  4. Log or dump the DSN (without secrets) during debugging to inspect its actual value.

Example fix

// before
$redis = RedisAdapter::createConnection(getenv('REDIS_URL')); // REDIS_URL='redis://'

// after - set a complete DSN
// REDIS_URL='redis://127.0.0.1:6379'
$redis = RedisAdapter::createConnection(getenv('REDIS_URL'));
Defensive patterns

Strategy: validation

Validate before calling

// Validate the DSN parses after scheme normalisation.
$test = preg_replace('#^(redis|rediss|valkey|valkeys)s?:#', 'file:', $dsn);
if (false === parse_url($test)) {
    throw new \InvalidArgumentException('Redis DSN is malformed: ' . $dsn);
}
$redis = RedisAdapter::createConnection($dsn);

Try / catch

try {
    $redis = RedisAdapter::createConnection($dsn);
} catch (\Symfony\Component\Cache\Exception\InvalidArgumentException $e) {
    if (str_contains($e->getMessage(), 'Invalid Redis DSN')) {
        // inspect the env var; likely truncated or unencoded credentials
        throw new \RuntimeException('Redis DSN invalid - check REDIS_URL', 0, $e);
    }
}

Prevention

When it happens

Trigger: A DSN like 'redis://' with nothing else (no host), a DSN with illegal characters that survive the scheme/auth rewrite, or a severely malformed string. Also possible with certain malformed unix socket DSNs or unencoded credentials containing reserved characters.

Common situations: Env var truncated or set to a placeholder like 'redis://'. Unencoded special characters in the password (e.g. '@' or ':' not percent-encoded). Copy-paste error leaving stray characters. DSN built by string concatenation with a missing part.

Related errors


AI-assisted analysis of symfony/symfony@3b11ffbe25 (2026-08-11). Data as JSON: /api/errors/5dfc3eb7aaf8b350. Report an issue: GitHub.

Appendix: source

Thrown at src/Symfony/Component/Cache/Traits/RedisTrait.php:124

        $auth = null;
        $params = preg_replace_callback('#^'.$scheme.':(//)?(?:(?:(?<user>[^:@]*+):)?(?<password>[^@]*+)@)?#', static function ($m) use (&$auth) {
            if (isset($m['password'])) {
                if (\in_array($m['user'], ['', 'default'], true)) {
                    $auth = rawurldecode($m['password']);
                } else {
                    $auth = [rawurldecode($m['user']), rawurldecode($m['password'])];
                }

                if ('' === $auth) {
                    $auth = null;
                }
            }

            return 'file:'.($m[1] ?? '');
        }, $dsn);

        if (false === $params = parse_url($params)) {
            throw new InvalidArgumentException('Invalid Redis DSN.');
        }

        $query = $hosts = [];

        $tls = 'rediss' === $scheme || 'valkeys' === $scheme;
        $tcpScheme = $tls ? 'tls' : 'tcp';

        if (isset($params['query'])) {
            parse_str($params['query'], $query);

            if (isset($query['host'])) {
                if (!\is_array($hosts = $query['host'])) {
                    throw new InvalidArgumentException('Invalid Redis DSN: query parameter "host" must be an array.');
                }
                foreach ($hosts as $host => $parameters) {
                    if (\is_string($parameters)) {
                        parse_str($parameters, $parameters);
                    }

View on GitHub (pinned to 3b11ffbe25)