{"record":{"id":"d743fd174698c4c7","repo":"redis/go-redis","slug":"redis-invalid-database-number-w-d743fd","errorCode":null,"errorMessage":"redis: invalid database number: %w","messagePattern":"redis: invalid database number: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sentinel.go","lineNumber":512,"sourceCode":"\to.PipelineWriteBufferSize = q.int(\"pipeline_write_buffer_size\")\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.PoolTimeout = q.duration(\"pool_timeout\")\n\to.DisableIdentity = q.bool(\"disableIdentity\")\n\to.IdentitySuffix = q.string(\"identitySuffix\")\n\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","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/sentinel.go#L494-L530","documentation":"In setupFailoverConnParams, the \"db\" query parameter of a failover URL must parse as an integer. If strconv.Atoi fails, the error is wrapped with %w and returned as this message — the underlying strconv error (e.g. strconv.Atoi: parsing \"abc\": invalid syntax) is preserved for errors.As/Is inspection.","triggerScenarios":"ParseFailoverURL with ?db=abc or ?db=1.5 in the query string.","commonSituations":"Putting a database name instead of an index in the query, environment-variable substitution failing so a placeholder like ${DB} leaks into the URL, or copy-paste leaving stray characters in the query.","solutions":["Fix the db query parameter to be a plain integer: redis://host:26379?db=2","Check the environment variable interpolation that builds the URL and verify the resolved value","Inspect the wrapped strconv error via errors.As to see the exact offending value"],"exampleFix":"// before\nurl := fmt.Sprintf(\"redis://host:26379?db=%s\", os.Getenv(\"REDIS_DB\")) // REDIS_DB=\"abc\"\n// after\nurl := fmt.Sprintf(\"redis://host:26379?db=%s\", os.Getenv(\"REDIS_DB\")) // REDIS_DB=\"2\"","handlingStrategy":"validation","validationCode":"u, err := url.Parse(raw)\nif err != nil { return err }\ndb := u.Query().Get(\"db\")\nif db != \"\" {\n    if _, err := strconv.Atoi(db); err != nil { return fmt.Errorf(\"db param %q is not an integer\", db) }\n}","typeGuard":null,"tryCatchPattern":"var serr *strconv.NumError\nopt, err := redis.ParseFailoverURL(raw)\nif err != nil && errors.As(err, &serr) { return fmt.Errorf(\"bad numeric param %q\", serr.Num) }","preventionTips":["Check env-var interpolation results before building the URL","Use plain integer DB indexes in query params","Validate the final URL string in tests"],"tags":["redis","sentinel","url-parsing","query-params"],"backgroundTag":"invalid-argument-value","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}