{"id":"1d12e716594b47c3","repo":"go-redis/redis","slug":"redis-unable-to-parse-addr-param-s","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":"osscluster.go","lineNumber":414,"sourceCode":"\to.MaxActiveConns = q.int(\"max_active_conns\")\n\to.PoolTimeout = q.duration(\"pool_timeout\")\n\to.ConnMaxLifetime = q.duration(\"conn_max_lifetime\")\n\tif q.has(\"conn_max_lifetime_jitter\") {\n\t\to.ConnMaxLifetimeJitter = min(q.duration(\"conn_max_lifetime_jitter\"), o.ConnMaxLifetime)\n\t}\n\to.ConnMaxIdleTime = q.duration(\"conn_max_idle_time\")\n\to.FailingTimeoutSeconds = q.int(\"failing_timeout_seconds\")\n\n\tif q.err != nil {\n\t\treturn nil, q.err\n\t}\n\n\t// addr can be specified as many times as needed\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.Addrs = append(o.Addrs, net.JoinHostPort(h, p))\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\nfunc (opt *ClusterOptions) clientOptions() *Options {\n\t// Clone MaintNotificationsConfig to avoid sharing between cluster node clients\n\tvar maintNotificationsConfig *maintnotifications.Config\n\tif opt.MaintNotificationsConfig != nil {\n\t\tconfigClone := *opt.MaintNotificationsConfig","sourceCodeStart":396,"sourceCodeEnd":432,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/osscluster.go#L396-L432","documentation":"Returned by setupClusterQueryParams when an ?addr=... query parameter (used to add extra seed nodes to a cluster URL) cannot be split by net.SplitHostPort into a non-empty host and port. Each addr value must be a complete host:port pair.","triggerScenarios":"A cluster URL like redis://host:7000/?addr=host2 (missing port) or ?addr=:7000 (missing host) or ?addr=host2:abc (non-numeric port).","commonSituations":"Copying only the hostname for additional nodes, forgetting the port, or a templating bug that drops the port segment.","solutions":["Make every addr value a full host:port pair.","Prefer ClusterOptions.Addrs with net.JoinHostPort to build each entry safely.","Validate each addr with net.SplitHostPort before building the URL."],"exampleFix":"// before\nopt, err := redis.ParseClusterURL(\"redis://host:7000/?addr=host2\")\n// after\nopt, err := redis.ParseClusterURL(\"redis://host:7000/?addr=host2:7000\")","handlingStrategy":"validation","validationCode":"func validAddrParam(addr string) bool {\n    h, p, err := net.SplitHostPort(addr); return err == nil && h != \"\" && p != \"\"\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include host and port in each ?addr= value.","Build addr values with net.JoinHostPort.","Validate with net.SplitHostPort before constructing the URL."],"tags":["config","url","cluster","validation"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}