{"record":{"id":"0a1a376f90badb8e","repo":"redis/go-redis","slug":"redis-unable-to-parse-addr-param-s-0a1a37","errorCode":null,"errorMessage":"redis: unable to parse addr param: %s","messagePattern":"redis: unable to parse addr param: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sentinel.go","lineNumber":521,"sourceCode":"\to.UnstableResp3 = q.bool(\"unstable_resp3\")\n\n\tif q.err != nil {\n\t\treturn nil, q.err\n\t}\n\n\tif tmp := q.string(\"db\"); tmp != \"\" {\n\t\tdb, err := strconv.Atoi(tmp)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"redis: invalid database number: %w\", err)\n\t\t}\n\t\to.DB = db\n\t}\n\n\taddrs := q.strings(\"addr\")\n\tfor _, addr := range addrs {\n\t\th, p, err := net.SplitHostPort(addr)\n\t\tif err != nil || h == \"\" || p == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"redis: unable to parse addr param: %s\", addr)\n\t\t}\n\n\t\to.SentinelAddrs = append(o.SentinelAddrs, net.JoinHostPort(h, p))\n\t}\n\n\tif o.TLSConfig != nil && q.has(\"skip_verify\") {\n\t\to.TLSConfig.InsecureSkipVerify = q.bool(\"skip_verify\")\n\t}\n\n\t// any parameters left?\n\tif r := q.remaining(); len(r) > 0 {\n\t\treturn nil, fmt.Errorf(\"redis: unexpected option: %s\", strings.Join(r, \", \"))\n\t}\n\n\treturn o, nil\n}\n\n// NewFailoverClient returns a Redis client that uses Redis Sentinel","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/sentinel.go#L503-L539","documentation":"Each \"addr\" query parameter of a failover URL must be a valid host:port pair (net.SplitHostPort must succeed and neither host nor port may be empty). Otherwise setupFailoverConnParams returns this error identifying the offending addr string.","triggerScenarios":"ParseFailoverURL with ?addr=localhost (no port), ?addr=:26379 (no host), ?addr=host:port:extra, or an unparseable bracketed IPv6 form.","commonSituations":"Listing sentinel addresses as bare hostnames without ports, forgetting to URL-encode/merge multiple addresses, or IPv6 addresses whose brackets were stripped by an interpolating config layer.","solutions":["Provide full host:port pairs: ?addr=sentinel1:26379&addr=sentinel2:26379","For IPv6 use bracketed form: ?addr=[::1]:26379","Trim whitespace/extra separators that leave an empty addr entry"],"exampleFix":"// before\n\"redis://mymaster?addr=sentinel-1\"          // no port\n// after\n\"redis://mymaster?addr=sentinel-1:26379\"","handlingStrategy":"validation","validationCode":"for _, a := range u.Query()[\"addr\"] {\n    if h, p, err := net.SplitHostPort(a); err != nil || h == \"\" || p == \"\" {\n        return fmt.Errorf(\"addr %q must be host:port\", a)\n    }\n}","typeGuard":null,"tryCatchPattern":"opt, err := redis.ParseFailoverURL(raw)\nif err != nil {\n    if strings.Contains(err.Error(), \"unable to parse addr\") { /* fix addr params */ }\n    return err\n}","preventionTips":["Always include a port for each sentinel addr","Use [bracketed] form for IPv6 hosts","Build addr lists programmatically with net.JoinHostPort"],"tags":["redis","sentinel","url-parsing","network"],"backgroundTag":"invalid-address-format","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}