{"id":"0469be227cdc306b","repo":"go-redis/redis","slug":"redis-newsentinelclient-nil-options","errorCode":null,"errorMessage":"redis: NewSentinelClient nil options","messagePattern":"redis: NewSentinelClient nil options","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"sentinel.go","lineNumber":691,"sourceCode":"\t\tif failover.opt.TLSConfig == nil {\n\t\t\treturn netDialer.DialContext(ctx, network, addr)\n\t\t}\n\t\treturn tls.DialWithDialer(netDialer, network, addr, failover.opt.TLSConfig)\n\t}\n}\n\n//------------------------------------------------------------------------------\n\n// SentinelClient is a client for a Redis Sentinel.\ntype SentinelClient struct {\n\t*baseClient\n}\n\n// NewSentinelClient returns a Redis Sentinel client.\n// Passing nil Options will cause a panic.\nfunc NewSentinelClient(opt *Options) *SentinelClient {\n\tif opt == nil {\n\t\tpanic(\"redis: NewSentinelClient nil options\")\n\t}\n\topt.init()\n\tc := &SentinelClient{\n\t\tbaseClient: &baseClient{\n\t\t\tapClosed: &atomic.Bool{},\n\t\t\topt:      opt,\n\t\t\tonClose:  &onCloseHooks{},\n\t\t},\n\t}\n\n\t// Initialize push notification processor using shared helper\n\t// Use void processor for Sentinel clients\n\tc.pushProcessor = NewVoidPushNotificationProcessor()\n\n\tc.initHooks(hooks{\n\t\tdial:    c.baseClient.dial,\n\t\tprocess: c.baseClient.process,\n\t})","sourceCodeStart":673,"sourceCodeEnd":709,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/sentinel.go#L673-L709","documentation":"NewSentinelClient panics when called with a nil *Options pointer. The constructor dereferences opt (opt.init()) immediately after this check, so the guard exists to fail loudly rather than produce a nil-pointer dereference deeper in setup. This is a programmer error, not a runtime/network condition.","triggerScenarios":"Calling redis.NewSentinelClient(nil) directly, or passing an uninitialised *redis.Options variable that was never assigned (e.g. var opt *redis.Options; NewSentinelClient(opt)).","commonSituations":"Conditional configuration where the options struct is built in a branch that did not execute, a helper that returns *redis.Options returning nil on a config-load failure, or refactoring that accidentally drops the options argument.","solutions":["Ensure the *redis.Options argument is non-nil before calling NewSentinelClient; construct it with &redis.Options{Addr: ...}.","If options come from a loader, abort early on the loader error instead of propagating a nil pointer.","Add a nil check at the call site and return a descriptive error to the caller."],"exampleFix":"// before\nvar opt *redis.Options\nc := redis.NewSentinelClient(opt)\n\n// after\nc := redis.NewSentinelClient(&redis.Options{Addr: \":26379\"})","handlingStrategy":"validation","validationCode":"func buildSentinelClient(opt *redis.Options) (*redis.SentinelClient, error) {\n    if opt == nil {\n        return nil, errors.New(\"redis.Options must not be nil\")\n    }\n    return redis.NewSentinelClient(opt), nil\n}","typeGuard":"func isNonNilOptions(opt *redis.Options) bool { return opt != nil }","tryCatchPattern":null,"preventionTips":["Treat *redis.Options as required: always construct it with &redis.Options{...} inline.","Never let a config-loader return *redis.Options directly without a non-nil guarantee; return (Options, error) instead.","Unit-test constructor call paths with a non-nil options fixture."],"tags":["sentinel","panic","configuration","nil-options"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}