juicedata/juicefs · error
redis parse %s: %s
Error message
redis parse %s: %s
What it means
After normalizing query parameters, newRedisMeta passes the full URL to go-redis's `redis.ParseURL` (pkg/meta/redis.go:141-144). ParseURL validates scheme (redis/rediss/redis-cluster etc.), host, port, and embedded credentials; any failure is wrapped as `redis parse %s: %s`. Unlike the earlier url.Parse check, this validates redis-specific URL semantics (scheme, port range, invalid user info).
Source
Thrown at pkg/meta/redis.go:141
skipVerify := query.pop("insecure-skip-verify")
certFile := query.pop("tls-cert-file")
keyFile := query.pop("tls-key-file")
caCertFile := query.pop("tls-ca-cert-file")
tlsServerName := query.pop("tls-server-name")
// Client-side caching options
clientCacheStr := query.pop("client-cache")
clientCache := clientCacheStr != "false" && clientCacheStr != ""
clientCacheSize := query.getInt("client-cache-size", "client_cache_size", 12800)
// Default TTL to prevent reading stale cache for a long time when the connection fails.
clientCacheExpiry := query.duration("client-cache-expire", "client_cache_expire", time.Minute)
clientCachePreload := query.getInt("client-cache-preload", "client_cache_preload", 0) // may cause conflict
u.RawQuery = values.Encode()
hosts := u.Host
opt, err := redis.ParseURL(u.String())
if err != nil {
return nil, fmt.Errorf("redis parse %s: %s", uri, err)
}
if opt.TLSConfig != nil {
opt.TLSConfig.ServerName = tlsServerName // use the host of each connection as ServerName
opt.TLSConfig.InsecureSkipVerify = skipVerify != ""
if certFile != "" {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, fmt.Errorf("get certificate error certFile:%s keyFile:%s error:%s", certFile, keyFile, err)
}
opt.TLSConfig.Certificates = []tls.Certificate{cert}
}
if caCertFile != "" {
caCert, err := os.ReadFile(caCertFile)
if err != nil {
return nil, fmt.Errorf("read ca cert file error path:%s error:%s", caCertFile, err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)View on GitHub (pinned to c9a67b23e8)
Solutions
- Use a supported scheme: `redis://`, `rediss://` (TLS), or `redis-cluster://`/`rediss-cluster://` as supported by your client version.
- Fix the port to a numeric value in 1-65535 (default 6379 may be omitted).
- Percent-encode username/password correctly (`%40` for `@`, `%25` for `%`); avoid malformed escapes.
- For sentinel deployments, do not encode sentinel addresses in the URL; configure them via query/addr format the driver expects.
Example fix
// before juicefs mount redis-sentinel://mypass@sentinel:26379/1 /jfs // unsupported scheme for ParseURL // after juicefs mount redis://mypass@sentinel:26379/1 /jfs
Defensive patterns
Strategy: validation
Validate before calling
// validate redis URL semantics before use
u, _ := url.Parse(metaURL)
if !strslice.Contains(u.Scheme, []string{"redis", "rediss", "redis-cluster", "rediss-cluster"}) {
return fmt.Errorf("unsupported redis scheme %q", u.Scheme)
}
if p := u.Port(); p != "" {
if n, err := strconv.Atoi(p); err != nil || n < 1 || n > 65535 { return fmt.Errorf("bad port %q", p) }
} Try / catch
if err != nil && strings.Contains(err.Error(), "redis parse ") {
return fmt.Errorf("redis URL rejected by go-redis ParseURL, check scheme/port/userinfo: %w", err)
} Prevention
- Match the scheme to the deployment: plain redis, rediss for TLS, cluster scheme for clusters.
- Never leave placeholder ports like :port in connection strings.
- Percent-encode userinfo; verify with url.Parse + u.User before running.
When it happens
Trigger: Using a scheme go-redis does not accept (e.g. `redis-sentinel://` where unsupported by ParseURL), an unparseable port (non-numeric or out of range), or a URL whose user-info cannot be decoded — even though generic url.Parse succeeded.
Common situations: Typing `redis://host:port` literally with a placeholder port; using the wrong scheme for the deployment (sentinel/cluster URLs vs plain redis); percent-encoded password containing malformed escapes like `%zz`.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- url parse %s: %s
- get certificate error certFile:%s keyFile:%s error:%s
- parse %s: %s
- Invalid endpoint: %v, error: %v
- parse url %s failed: %s
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/4ea8c02f30a9aaab.
Report an issue: GitHub.