fix: carry errorCode through provider error events - #2015
Conversation
A handler registered with OpenFeatureAPI.onProviderError always saw getErrorCode() as null. Two places dropped it. EventDetails.fromProviderEventDetails, the only path from a provider-emitted ProviderEventDetails to the EventDetails handed to API-level handlers, copied flagsChanged, eventMetadata and message but not errorCode. It failed silently: EventDetails extends ProviderEventDetails, so getErrorCode() compiles and returns null rather than failing to compile, and there is no public way to observe a provider's events directly to work around it. OpenFeatureAPI.emitError, which raises PROVIDER_ERROR when a provider fails to initialise, built its ProviderEventDetails from the exception's message only, even though it holds an OpenFeatureError that exposes getErrorCode(). Errors the SDK raises itself therefore reached handlers with no code either, which is what spec 5.1.5 asks for. errorCode was the only field missing from the conversion: ProviderEventDetails declares four fields and the other three were already copied. emitReady still sets no error code, so PROVIDER_READY events are unchanged. EventsTest.shouldHaveAllProperties now asserts errorCode alongside the other fields, since that is the test that should have caught this. Fixes open-feature#2014 Signed-off-by: Yu Chou <yuchou87@gmail.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Included review availability: Your plan includes up to 2 reviews per rolling hour; 1 remains after this review. 📝 WalkthroughWalkthroughProvider error codes now propagate through ChangesProvider error code propagation
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This localized change preserves provider error codes for error handlers and adds coverage for both affected paths; no actionable merge-blocking risk remains after normal checks and review. Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|



What
Fixes #2014. A handler registered with
OpenFeatureAPI.onProviderErroralways sawdetails.getErrorCode()asnull. Two places dropped it, and the PR fixes both.1. The conversion to
EventDetailsdid not copy itEventDetails.fromProviderEventDetails(...)is the only path from a provider-emittedProviderEventDetailsto theEventDetailshanded to API-level handlers, and its builderchain simply did not mention
errorCode:It failed silently rather than loudly:
EventDetails extends ProviderEventDetails, sogetErrorCode()compiles and returnsnull. And it could not be worked around fromapplication code —
EventProvider.setEventProviderListenerandEventProvider.attachareboth package-private, so there is no public way to observe a provider's events directly
and read the original
ProviderEventDetails.errorCodewas the only field affected.ProviderEventDetailsdeclares exactly fourfields —
flagsChanged,message,eventMetadata,errorCode— and the other three werealready copied, so this is a missing line rather than a conversion that needs realigning.
2.
OpenFeatureAPI.emitErrornever read the code it was holdingThis one I found while preparing the fix for the first, and it is why the PR is two lines
rather than one.
emitErrorraisesPROVIDER_ERRORwhen a provider fails to initialise.It takes an
OpenFeatureError, which declaresgetErrorCode(), but built its eventdetails from the message alone:
So even with the conversion fixed, a
PROVIDER_ERRORthe SDK raises itself still reachedhandlers with no code — including for
FatalErrorandProviderNotReadyError, where thecode is precisely what a handler would act on. Spec 5.1.5 asks for it to be populated.
emitReadyis left alone: it genuinely has no error code, soPROVIDER_READYevents areunchanged.
Why this is a
fix:and not a breaking changeNo consumer could have depended on
nullas a signal, because there was no way to obtaina non-null value through this path.
FeatureProviderStateManager.onEmitreadserrorCodeoff the original
ProviderEventDetailsrather than the convertedEventDetails, soprovider state transitions are untouched.
Testing
EventsTest.shouldHaveAllPropertiesnow assertserrorCodealongside the other fields.That is the existing test that should have caught this, and it exercises the
user-visible path through a real handler rather than the package-private conversion.
EventsTest.errorsRaisedBySdkMustCarryErrorCodecovers the second half: a provider thatfails initialisation with
FatalError, and a handler that must seePROVIDER_FATAL.It carries the
@Specificationannotation for 5.1.5, which nothing in the suite claimedbefore.
EventDetailsTestcovers the conversion directly, including that an absent code staysnull.Both halves were verified to fail without their fix: reverting the
EventDetailslinefails
shouldHaveAllPropertiesand two of the threeEventDetailsTestcases, andreverting the
emitErrorchange failserrorsRaisedBySdkMustCarryErrorCode../mvnw testpasses — 552 tests, 0 failures, 0 errors — and./mvnw spotless:checkisclean, against
mainat5bf9f56.Note
Happy to split the
emitErrorhalf into its own PR if you would rather keep the twoapart; I kept them together because they are the same defect reaching the user the same
way, and fixing only the conversion leaves
onProviderErrorwithout a code for exactlythe failures that matter most.