open-feature / open-feature/go-sdk
[BUG] multiprovider: toProviderResolutionDetail drops PROVIDER_NOT_READY and PROVIDER_FATAL error codes
- Dominant language
- Go
- Stars
- 250
- Forks
- 62
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 25
Description
## Observed behavior
`toProviderResolutionDetail` in `openfeature/multi/isolation.go` switches on `evalDetails.ErrorCode` but has no case for `ProviderNotReadyCode` or `ProviderFatalCode`. When a wrapped provider returns either, neither `resolutionErr` nor `reason` is assigned, so both stay zero-valued. Since `ProviderResolutionDetail.Error()` checks `if p.ResolutionError.code == ""`, it then returns nil.
Net effect: a genuine PROVIDER_NOT_READY or PROVIDER_FATAL from a child provider is silently converted into what looks like a successful resolution with no reason set.
## Expected Behavior
Both codes preserved with `Reason` set to `of.ErrorReason`, like the other codes in that switch. Constructors already exist:
```go
case of.ProviderNotReadyCode:
resolutionErr = of.NewProviderNotReadyResolutionError(evalDetails.ErrorMessage)
reason = of.ErrorReason
case of.ProviderFatalCode:
resolutionErr = of.NewProviderFatalResolutionError(evalDetails.ErrorMessage)
reason = of.ErrorReason
```
Worth deciding whether an unknown code should also fall back to `GeneralCode` + `ErrorReason` rather than silently producing a no-error detail, so the switch stays robust as new codes are added.
## Steps to reproduce
Configure a multi-provider whose child returns `ProviderNotReadyCode` (or `ProviderFatalCode`), evaluate through it, and inspect the resolution detail — error code and reason are both absent, and `Error()` reports nil.
## Notes
Found while reviewing #541, but independent of it: `hookIsolator` calls the wrapped provider's evaluation methods directly rather than going through `client.evaluate`, so this is pre-existing.
Contributor guide
Research direction
Start in openfeature/multi/isolation.go at toProviderResolutionDetail and trace how a wrapped provider's evaluation result becomes ProviderResolutionDetail. Reproduce a child result using ProviderNotReadyCode or ProviderFatalCode, then verify the resulting detail preserves the error code and reason and that Error() is non-nil. Also check the switch's behavior for unknown codes before deciding whether a fallback is needed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend-api-design
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 78/100