File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -123,14 +123,21 @@ export function buildRefreshOnRejectedBearerLink(authenticationManager?: Authent
123123 let activeSubscription : { unsubscribe ( ) : void } | undefined ;
124124
125125 const runOnce = ( ) => {
126- // Tear down the previous attempt so its `complete`/`error` events
127- // can't race the retry.
126+ // Tear down any previous attempt before starting a new one.
128127 activeSubscription ?. unsubscribe ( ) ;
129128 activeSubscription = next ( operation ) . subscribe ( {
130129 next : ( result ) => {
131130 const response = operation . getContext ( ) . response as Response | undefined ;
132131 if ( ! attemptedRefresh && response ?. headers ?. get ( BEARER_REJECTED_HEADER ) === 'true' ) {
133132 attemptedRefresh = true ;
133+ // Unsubscribe synchronously so that BatchHttpLink's upcoming
134+ // synchronous `complete` call (which immediately follows `next`
135+ // in its promise chain) is a no-op on the now-closed subscriber.
136+ // Without this, `observer.complete()` would fire before the retry
137+ // emits a value, triggering Apollo's "link chain completed without
138+ // emitting a value" error.
139+ activeSubscription ?. unsubscribe ( ) ;
140+ activeSubscription = undefined ;
134141 // Mark the access token as known-bad so the auth-headers link
135142 // can't reuse it, then refresh and re-run the chain.
136143 authenticationManager . jwtToken = undefined ;
You can’t perform that action at this time.
0 commit comments