go-redis/redis · critical
redis: NewClient nil options
Error message
redis: NewClient nil options
What it means
NewClient panics with 'redis: NewClient nil options' when the passed *Options pointer is nil. The constructor deliberately panics (documented at redis.go:1918) rather than returning an error because a client with no options has no Addr, no pool, and cannot function - it is a programmer error, not a runtime condition. The panic surfaces immediately at startup instead of producing confusing failures on the first command.
Source
Thrown at redis.go:1921
*baseClient
cmdable
// cscLifecycleOwner keeps the canonical Client wrapper (the one whose GC
// cleanup owns the drainer) reachable while a WithTimeout clone can still
// serve from its cache. Nil on the canonical wrapper and on non-CSC clones.
cscLifecycleOwner *Client
autopipelinerMu *sync.Mutex // guards the autopipeliner fields against concurrent first-call creation
autopipeliner *AutoPipeliner // blocking face (Client.AutoPipeline)
asyncAutopipeliner *AutoPipeliner // deferred face (Client.AsyncAutoPipeline)
autopipelinerClosed bool // set by Close: refuse to resurrect a pipeliner on a closed client
}
// NewClient returns a client to the Redis Server specified by Options.
// Passing nil Options will cause a panic.
func NewClient(opt *Options) *Client {
if opt == nil {
panic("redis: NewClient nil options")
}
// clone to not share options with the caller
opt = opt.clone()
opt.init()
// Push notifications are always enabled for RESP3 (cannot be disabled)
c := Client{
baseClient: &baseClient{
apClosed: &atomic.Bool{},
opt: opt,
onClose: &onCloseHooks{},
himport: newHImportRegistry(),
},
}
c.init()
// Initialize push notification processor using shared helperView on GitHub (pinned to 36d97525cd)
Solutions
- Ensure the *redis.Options passed to NewClient is always non-nil - construct it inline with &redis.Options{Addr: ...} at minimum.
- If options come from a loader/builder, have it always return a valid *redis.Options (defaulting fields) and never nil; add a unit test asserting non-nil.
- Guard the call site: if opt == nil { opt = &redis.Options{Addr: "localhost:6379"} } before NewClient, or return an error from your own factory.
- Run go vet / staticcheck to catch obviously-nil pointers; add a constructor wrapper that fails fast with a clear error instead of a panic.
Example fix
// before
client := redis.NewClient(optFromConfig) // optFromConfig is nil
// after
opt := optFromConfig
if opt == nil {
opt = &redis.Options{Addr: "localhost:6379"}
}
client := redis.NewClient(opt) Defensive patterns
Strategy: validation
Validate before calling
func newClient(opt *redis.Options) (*redis.Client, error) {
if opt == nil {
return nil, errors.New("redis options must not be nil")
}
if opt.Addr == "" {
opt.Addr = "localhost:6379"
}
return redis.NewClient(opt), nil
} Type guard
// Guard against a typed-nil or unset pointer before constructing.
func validOptions(opt *redis.Options) bool {
return opt != nil
} Try / catch
// Go has no catch; use recover at a goroutine boundary only as a last resort.
defer func() {
if r := recover(); r != nil {
log.Fatalf("redis client init failed: %v", r)
}
}()
client := redis.NewClient(opt) Prevention
- Always initialize options inline: &redis.Options{Addr: ...}.
- Make option loaders return a non-nil *redis.Options with defaults, never nil.
- Wrap NewClient in your own factory that validates inputs and returns an error.
- Add a unit test asserting your config builder returns non-nil options.
When it happens
Trigger: Calling redis.NewClient(nil); passing a *redis.Options variable that was declared but never initialized (still nil); loading options from a builder/config function that returns nil on an unhandled branch; conditionally constructing options where the nil case is not covered.
Common situations: Config loaded from environment/flags where no values were set so the builder returns nil; DI containers or factories that return a typed nil (*redis.Options)(nil); tests that stub the options loader to return nil; refactoring that moves option construction behind a helper which forgets to initialize the struct.
Related errors
- redis: NewRing nil options
- redis: NewUniversalClient nil options
- redis: NewSentinelClient nil options
- redis: NewFailoverClusterClient nil options
- redis: NewClusterClient nil options
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/7e355419b4ba8570.json.
Report an issue: GitHub.