fix(calling): don't fail startCall when reaction listener is blocked … - #6065
Merged
Conversation
…by meeting policy The stateful client's CallSubscriber unconditionally creates a ReactionSubscriber for every call, which synchronously registers a 'reaction' listener via ReactionCallFeature.on(). For Teams-identity outbound group/PSTN calls the Calling SDK rejects this registration with an ExpectedError (code=403 subCode=45802 EVENT_SUBSCRIBE_FAIL_POLICY, "Unable to register listener due to meeting policy"). Because the construction was not guarded, the exception propagated out of CallAgent.startCall / join, so the returned Call/TeamsCall was null even though the app never uses reactions. Toggling the Teams meeting-policy reactions setting has no effect because these are group/PSTN calls, not meetings, and the subscription happens unconditionally. Wrap the ReactionSubscriber creation in the existing _safeSubscribe helper (purpose-built to stop a throwing subscriber from breaking call setup) so the expected policy error is tee'd to state instead of aborting the call. Adds a regression test asserting the call is still set up when the reaction listener registration throws 403/45802. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bluk16
requested review from
JamesBurnside,
dmceachernmsft,
edwardlee-msft,
mgamis-msft and
prabhjot-msft
July 21, 2026 13:19
prabhjot-msft
approved these changes
Jul 21, 2026
mgamis-msft
approved these changes
Jul 21, 2026
Contributor
@azure/communication-react jest test coverage for beta.
|
Contributor
@azure/communication-react jest test coverage for stable.
|
JamesBurnside
approved these changes
Jul 22, 2026
edwardlee-msft
approved these changes
Jul 22, 2026
Contributor
📦 Chat bundle size
Total change: +373 B |
Contributor
📦 Calling bundle size
Total change: +2.3 KB |
Contributor
📦 CallWithChat bundle size
Total change: +2.3 KB |
prabhjot-msft
approved these changes
Jul 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
From Icm: https://portal.microsofticm.com/imp/v5/incidents/details/21000001115074/summary
startCall(andjoin) can throw and return anullCall when the app has no involvement with reactions at all, because the stateful client unconditionally registers a'reaction'listener during call wiring. On calls where that registration is policy-gated by the Calling SDK — notably Teams-identity outbound Group / PSTN calls — the SDK throws anExpectedError(code=403 subCode=45802 EVENT_SUBSCRIBE_FAIL_POLICY, "Unable to register listener due to meeting policy"). That error propagates out ofCallAgent.startCall, aborting call setup even though the application never uses reactions.This makes reactions — an optional feature — a hard dependency of establishing a call.
Root cause
CallSubscriber's constructor unconditionally constructs aReactionSubscriber:ReactionSubscriber's constructor synchronously callsthis._reaction.on('reaction', …). When that.on()is rejected by meeting policy, the exception is thrown duringCallSubscriberconstruction, which happens as part ofstartCall/join. Nothing catches it, so it surfaces to the caller and the returnedCallisnull.Other optional-feature subscribers in this file (captions, real-time text, local recording) are already guarded against exactly this class of failure via the
_safeSubscribehelper; the reaction subscriber was missing that guard.Fix
Wrap the
ReactionSubscriberconstruction in the existing_safeSubscribe(...)helper, which try/catches the subscription and tees any error to state viateeErrorToStateinstead of letting it abort call setup:This mirrors the pattern already used for the other policy-gated optional-feature subscribers, so the behavior is consistent: a blocked reaction subscription no longer breaks a call, and the failure is still observable through
latestErrorsrather than being swallowed silently.Testing
Reactionfeature's.on()throw the 403 /EVENT_SUBSCRIBE_FAIL_POLICYerror and asserts the call is still set up in state (and the error is tee'd tolatestErrors['Call.on'])._safeSubscribewrap makes exactly this one test fail; with the fix the fullcalling-stateful-clientsuite passes (70/70).Change type
Bug fix (patch). Change files added for both the stable and beta channels.