redis/redis-py · error · ValueError

Redis URL must specify one of the following schemes…

Error message

Redis URL must specify one of the following schemes (redis://, rediss://, unix://)

What it means

Raised as ValueError by parse_url when the URL does not start (case-insensitively) with redis://, rediss://, or unix://. The check requires the '://' so a bare scheme like 'redis:foo' is also rejected. redis-py only supports these three schemes; anything else is a configuration error.

Solutions

  1. Prefix the value with redis:// (e.g. redis://localhost:6379/0), rediss:// for TLS, or unix:///path/to/socket.sock.
  2. Strip whitespace from environment-supplied URLs before passing them in.
  3. If you have a bare host/port, use redis.Redis(host=..., port=...) instead of from_url.

Example fix

# before
r = redis.Redis.from_url(os.environ['REDIS_HOST'])  # e.g. 'localhost:6379'
# after
r = redis.Redis.from_url('redis://' + os.environ['REDIS_HOST'])
Defensive patterns

Strategy: validation

Validate before calling

def is_supported_redis_url(url: str) -> bool:
    return isinstance(url, str) and url.lower().startswith(('redis://', 'rediss://', 'unix://'))

url = os.environ.get('REDIS_URL', '').strip()
if not is_supported_redis_url(url):
    raise ValueError(f'REDIS_URL must start with redis://, rediss://, or unix:// — got {url!r}')
r = redis.Redis.from_url(url)

Type guard

def is_supported_redis_url(url) -> bool:
    return isinstance(url, str) and url.lower().startswith(('redis://', 'rediss://', 'unix://'))

Try / catch

try:
    r = redis.Redis.from_url(maybe_url)
except ValueError as e:
    if 'must specify one of the following schemes' in str(e):
        maybe_url = 'redis://' + maybe_url
        r = redis.Redis.from_url(maybe_url)
    else:
        raise

Prevention

When it happens

Trigger: Calling redis.Redis.from_url('localhost:6379'), from_url('redis:localhost'), from_url('tcp://host'), or from_url('') — any string missing a recognized scheme prefix.

Common situations: Forgetting the scheme and passing host:port. Using an env var that was meant for another client (e.g. a 'tcp://' or 'redis-cluster://' URL). Trailing/leading whitespace in the env var. Empty REDIS_URL.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/2ced58bfb6fc5b41. Report an issue: GitHub.

Appendix: source

Thrown at redis/connection.py:2351

    "retry_on_error": list,
    "max_connections": int,
    "health_check_interval": int,
    "ssl_check_hostname": to_bool,
    "ssl_include_verify_flags": parse_ssl_verify_flags,
    "ssl_exclude_verify_flags": parse_ssl_verify_flags,
    "ssl_min_version": int,
    "timeout": float,
    "protocol": int,
    "legacy_responses": to_bool,
}


def parse_url(url):
    # Scheme names are case-insensitive (RFC 3986), so normalize before the
    # prefix check; the "://" is required so a URL like "redis:foo" (which
    # urlparse would still report as the "redis" scheme) is rejected.
    if not url.lower().startswith(("redis://", "rediss://", "unix://")):
        raise ValueError(
            "Redis URL must specify one of the following "
            "schemes (redis://, rediss://, unix://)"
        )

    url = urlparse(url)
    kwargs = {}

    for name, value in parse_qs(url.query).items():
        if value and len(value) > 0:
            # parse_qs() already percent-decodes query values, so use the value
            # as-is; unquoting again here would double-decode (e.g. "%2520" ->
            # "%20" -> " "). See issue #4208.
            value = value[0]
            parser = URL_QUERY_ARGUMENT_PARSERS.get(name)
            if parser:
                try:
                    kwargs[name] = parser(value)
                except (TypeError, ValueError):

View on GitHub (pinned to 6a6b581b48)