Skip to content

fix: retry refresh only on transient failures, not on de-auth - #245

Open
major0 wants to merge 1 commit into
ProtonMail:masterfrom
major0:fix/refresh-retry-skip-deauth
Open

fix: retry refresh only on transient failures, not on de-auth#245
major0 wants to merge 1 commit into
ProtonMail:masterfrom
major0:fix/refresh-retry-skip-deauth

Conversation

@major0

@major0 major0 commented Jul 29, 2026

Copy link
Copy Markdown

retryRefreshFailed (added in 0f1b604, "feat(BRIDGE-586): add retry-condition for refresh failed") retries a failed /auth/v4/refresh when the response is 400 or 422, and does not retry 5xx. This appears inverted:

  • 400 and 422 on /auth/v4/refresh are the permanent de-auth signal. authRefresh in client.go treats those exact status codes as de-auth (running the de-auth handlers). Retrying them cannot succeed with the same dead refresh token; with the default retryCount of 3 it issues four refresh attempts, hammering the auth endpoint and delaying the de-auth signal to callers.
  • 5xx is a transient server error that is the normal candidate for a retry, yet it is currently excluded.

Narrow the condition to retry only genuinely transient failures: no response reached the client (network error / timeout) or a 5xx server error. 400/422 now fall through immediately so the de-auth path fires on the first response. The accompanying test's expectations are corrected to match (400/422 -> no retry, 500 -> retry).

Note: BRIDGE-586 broke unit tests in https://github.com/major0/proton-utils.git due to the seemingly inverted retry logic.

Refs:

@major0
major0 force-pushed the fix/refresh-retry-skip-deauth branch from 50ce7e9 to 8e5014d Compare July 31, 2026 13:44
retryRefreshFailed (added in 0f1b604, "feat(BRIDGE-586): add
retry-condition for refresh failed") retries a failed
/auth/v4/refresh when the response is 400 or 422, and does not retry
5xx. This appears inverted:

  - 400 and 422 on /auth/v4/refresh are the permanent de-auth signal.
    authRefresh in client.go treats those exact status codes as
    de-auth (running the de-auth handlers). Retrying them cannot
    succeed with the same dead refresh token; with the default
    retryCount of 3 it issues four refresh attempts, hammering the
    auth endpoint and delaying the de-auth signal to callers.
  - 5xx is a transient server error that is the normal candidate for
    a retry, yet it is currently excluded.

Narrow the condition to retry only genuinely transient failures: no
response reached the client (network error / timeout) or a 5xx server
error. 400/422 now fall through immediately so the de-auth path fires
on the first response. The accompanying test's expectations are
corrected to match (400/422 -> no retry, 500 -> retry).

Note: BRIDGE-586 is an internal ticket with no public rationale, so
this assumes the original status set was inverted. If there is a
specific transient 400/422 case this was meant to paper over (e.g. a
refresh-token rotation race), please advise and we can scope the retry
to that case instead.

Ref: ProtonMail/go-proton-api@0f1b604
@major0
major0 force-pushed the fix/refresh-retry-skip-deauth branch from 8e5014d to 25c4da4 Compare August 11, 2026 15:17
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