open-feature / open-feature/go-sdk
[BUG] multiprovider: a failed Init leaves the event channel open forever and never shuts down providers that did initialize
- Dominant language
- Go
- Stars
- 249
- Forks
- 61
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 20
Description
## Observed behavior
When `InitWithContext` fails, it returns early — before `close(p.outboundEvents)` and before `shutdownFunc` is assigned:
https://github.com/open-feature/go-sdk/blob/6b0824c6c7b9b69e40f26aedcc4406ad4d3a5cec/openfeature/multi/multiprovider.go#L403-L430
`ShutdownWithContext` then short-circuits on `!p.initialized`, so there is no recovery path:
https://github.com/open-feature/go-sdk/blob/6b0824c6c7b9b69e40f26aedcc4406ad4d3a5cec/openfeature/multi/multiprovider.go#L569-L576
Observed:
```
Init error = Provider bad: context deadline exceeded ; Status() = "ERROR"
shutdownFunc nil after failed Init = true
consumer goroutine on EventChannel() blocks forever after failed Init
```
Two leaks follow. Any consumer ranging over `EventChannel()` blocks permanently, since the channel is never closed. And inner providers that *did* initialize successfully never receive `Shutdown`, so their connections and goroutines leak.
## Expected Behavior
A failed `InitWithContext` should leave the provider in a state where cleanup is possible:
- close `outboundEvents` (or make `ShutdownWithContext` handle the partially-initialized state rather than short-circuiting), and
- shut down the inner providers that did initialize, per [1.1.2.3](https://openfeature.dev/specification/sections/flag-evaluation#requirement-1123) and [§2.5](https://openfeature.dev/specification/sections/providers#25-shutdown).
## Steps to reproduce
```go
// one provider's InitWithContext returns an error; the other succeeds
mp, _ := multi.NewProvider(multi.StrategyFirstMatch,
multi.WithProvider("bad", &failingInitProvider{}),
multi.WithProvider("good", &okProvider{}))
err := mp.InitWithContext(ctx, of.EvaluationContext{}) // non-nil
go func() { for range mp.EventChannel() {} }() // never returns
mp.ShutdownWithContext(ctx) // no-ops; "good" never shut down
```
Contributor guide
Research direction
Start in openfeature/multi/multiprovider.go at InitWithContext and ShutdownWithContext, then inspect EventChannel and the initialization path for partial success. Reproduce the failing-provider and successful-provider scenario from the issue. Done means a failed initialization permits cleanup, closes EventChannel, and shuts down providers that initialized successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100