Skip to content

fix(pair): let a failed channel open be retried - #21158

Open
dschom wants to merge 2 commits into
fxa-14444from
fxa-14483
Open

fix(pair): let a failed channel open be retried#21158
dschom wants to merge 2 commits into
fxa-14444from
fxa-14483

Conversation

@dschom

@dschom dschom commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Because

  • open() resolved on a failed connect, so openChannel()'s catch never cleared its client reference; every later call returned early on "Pairing channel already open!".
  • The supplicant could not retry a channel after a flaky network or a consumed channel id, short of a full page reload.
  • create() rethrows and attaches its listeners before connected; open() did neither.

This pull request

  • Rejects from open() once the error event has gone out.
  • Guards openChannel()'s catch with isPostCompletionReconnect().
  • Attaches the channel listeners before dispatching connected.
  • Adds regression tests for the retry path, the listener order, and the reload guard.

Issue that this pull request solves

Closes: FXA-14483

Checklist

Put an x in the boxes that apply

  • My commit is GPG signed.
  • If applicable, I have modified or added tests which pass locally.
  • I have added necessary documentation (if appropriate).
  • I have verified that my changes render correctly in RTL (if appropriate).
  • I have manually reviewed all AI generated code.

How to review (Optional)

  • Key files/areas to focus on: the open() catch in pairing-channel.ts, and the openChannel() catch in pairing-supplicant-integration.ts.
  • Suggested review order: the new reject in pairing-channel.ts, then the integration guard that absorbs it, then the tests.
  • Risky or complex parts: the guard. With open() rejecting, the FXA-13616 post-OAuth Android reload would otherwise navigate to the failure screen. Removing the guard fails open failure while still Connecting is ignored when completion marker is set with Expected "connecting", Received "failed".

Screenshots (Optional)

Please attach the screenshots of the changes made in case of change in user interface.

Other information (Optional)

  • Stacked on fix(settings): stop reporting expected pairing channel closes to Sentry #21157 (FXA-14444). Base is fxa-14444; retarget to main once that merges.
  • ~15 lines in pairing-supplicant-integration.ts are prettier churn from the pre-commit hook; the actual change there is the 7-line guard.
  • The listener reorder has no repro today — no await separates the dispatch from the registration. Included because create() treats the order as load-bearing.
  • FXA-14446 (TLS Alert: DECODE_ERROR) is another connect rejection reaching this catch block; expect a textual conflict if it lands first.

Because:

- open() resolved on a failed connect, so openChannel()'s catch never
  ran and never cleared its client reference; every later call then
  returned early on "Pairing channel already open!".
- The supplicant could not retry a channel after a flaky network or a
  consumed channel id, short of a full page reload.
- create() rethrows and attaches its listeners before `connected`;
  open() did neither.

This commit:

- Rejects from open() once the error event has gone out.
- Guards openChannel()'s catch with isPostCompletionReconnect() so the
  post-OAuth reload still reaches the success screen.
- Attaches the channel listeners before dispatching `connected`.
- Covers the retry path, the listener order, and the reload guard.

Closes #FXA-14483
// A consumed channel refusing the socket is the post-OAuth reload, not a
// failure. open() dispatches an `error` event before it rejects, so
// handleChannelError has usually settled the state by now; fail() is a
// no-op once it has, and still catches the errors raised before any

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once it has what?

// Send OAuth request to authority
if (!this._channel) {
throw new Error('Channel no longe exists!')
throw new Error('Channel no longe exists!');

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo., should be 'Channel no longer exists!'

@dschom
dschom marked this pull request as ready for review September 4, 2026 23:58
@dschom
dschom requested a review from a team as a code owner September 4, 2026 23:58
Because:

- The guard comment's "no-op once it has" had no clear antecedent.
- The channel-missing error read "no longe exists".

This commit:

- Rewrites the openChannel guard comment to say why fail() still runs
  for the errors that reject before any event is dispatched.
- Corrects the thrown message to "Channel no longer exists!".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant