{"record":{"id":"4ea8c02f30a9aaab","repo":"juicedata/juicefs","slug":"redis-parse-s-s","errorCode":null,"errorMessage":"redis parse %s: %s","messagePattern":"redis parse (.+?): (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/redis.go","lineNumber":141,"sourceCode":"\tskipVerify := query.pop(\"insecure-skip-verify\")\n\tcertFile := query.pop(\"tls-cert-file\")\n\tkeyFile := query.pop(\"tls-key-file\")\n\tcaCertFile := query.pop(\"tls-ca-cert-file\")\n\ttlsServerName := query.pop(\"tls-server-name\")\n\n\t// Client-side caching options\n\tclientCacheStr := query.pop(\"client-cache\")\n\tclientCache := clientCacheStr != \"false\" && clientCacheStr != \"\"\n\tclientCacheSize := query.getInt(\"client-cache-size\", \"client_cache_size\", 12800)\n\t// Default TTL to prevent reading stale cache for a long time when the connection fails.\n\tclientCacheExpiry := query.duration(\"client-cache-expire\", \"client_cache_expire\", time.Minute)\n\tclientCachePreload := query.getInt(\"client-cache-preload\", \"client_cache_preload\", 0) // may cause conflict\n\tu.RawQuery = values.Encode()\n\n\thosts := u.Host\n\topt, err := redis.ParseURL(u.String())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"redis parse %s: %s\", uri, err)\n\t}\n\tif opt.TLSConfig != nil {\n\t\topt.TLSConfig.ServerName = tlsServerName // use the host of each connection as ServerName\n\t\topt.TLSConfig.InsecureSkipVerify = skipVerify != \"\"\n\t\tif certFile != \"\" {\n\t\t\tcert, err := tls.LoadX509KeyPair(certFile, keyFile)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"get certificate error certFile:%s keyFile:%s error:%s\", certFile, keyFile, err)\n\t\t\t}\n\t\t\topt.TLSConfig.Certificates = []tls.Certificate{cert}\n\t\t}\n\t\tif caCertFile != \"\" {\n\t\t\tcaCert, err := os.ReadFile(caCertFile)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"read ca cert file error path:%s error:%s\", caCertFile, err)\n\t\t\t}\n\t\t\tcaCertPool := x509.NewCertPool()\n\t\t\tcaCertPool.AppendCertsFromPEM(caCert)","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/redis.go#L123-L159","documentation":"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).","triggerScenarios":"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.","commonSituations":"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`.","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."],"exampleFix":"// before\njuicefs mount redis-sentinel://mypass@sentinel:26379/1 /jfs // unsupported scheme for ParseURL\n// after\njuicefs mount redis://mypass@sentinel:26379/1 /jfs","handlingStrategy":"validation","validationCode":"// validate redis URL semantics before use\nu, _ := url.Parse(metaURL)\nif !strslice.Contains(u.Scheme, []string{\"redis\", \"rediss\", \"redis-cluster\", \"rediss-cluster\"}) {\n\treturn fmt.Errorf(\"unsupported redis scheme %q\", u.Scheme)\n}\nif p := u.Port(); p != \"\" {\n\tif n, err := strconv.Atoi(p); err != nil || n < 1 || n > 65535 { return fmt.Errorf(\"bad port %q\", p) }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"redis parse \") {\n\treturn fmt.Errorf(\"redis URL rejected by go-redis ParseURL, check scheme/port/userinfo: %w\", err)\n}","preventionTips":["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."],"tags":["redis","url","go-redis","config"],"backgroundTag":"invalid-url-format","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}