-
-
Notifications
You must be signed in to change notification settings - Fork 453
Description
Bug Description
The retry backoff formula in gotrue's _start_auto_refresh_token causes an OverflowError: timestamp out of range for platform time_t when a token refresh fails with AuthRetryableError.
Note: This bug is in the gotrue package (dependency of supabase), but since both supabase-community/gotrue-py and supabase/auth-py are archived, filing here.
Root Cause
In both gotrue/_sync/gotrue_client.py (line 1066) and gotrue/_async/gotrue_client.py (line 1070), the retry interval is computed as:
RETRY_INTERVAL ** (self._network_retries * 100)Where RETRY_INTERVAL = 2 (from gotrue/constants.py).
On the first retry (_network_retries = 1), this computes:
2 ** (1 * 100) = 2^100 = 1.267 × 10^30 milliseconds
This value is then passed to Timer(value / 1000, ...) in gotrue/timer.py:30, resulting in a threading.Timer with an interval of 1.267 × 10^27 seconds — which overflows the platform's time_t limit.
Expected Behavior
The retry backoff should use a reasonable exponential backoff formula, e.g.:
RETRY_INTERVAL * (2 ** self._network_retries)Which would give: 4ms, 8ms, 16ms, ... instead of 2^100 ms, 2^200 ms, ...
Or alternatively, cap the retry interval to a safe maximum value.
Reproduction
- Create a Supabase client with
auto_refresh_token=True - Authenticate with
sign_in_with_password - When the token expires and the auto-refresh encounters a transient network error (
AuthRetryableError), the overflow occurs
Error from Sentry (Production)
OverflowError: timestamp out of range for platform time_t
File "threading.py", line 1431, in run
self.finished.wait(self.interval)
File "threading.py", line 655, in wait
signaled = self._cond.wait(timeout)
File "threading.py", line 359, in wait
gotit = waiter.acquire(True, timeout)
Variable: timeout = 1.2676506002282294e+27
Environment
- gotrue: 2.12.3 (also confirmed unfixed in 2.12.4)
- supabase: 2.18.0
- Python: CPython 3.12.12
- Platform: Linux (Docker container)
Affected Code
gotrue/_sync/gotrue_client.py around line 1060:
except Exception as e:
if (
isinstance(e, AuthRetryableError)
and self._network_retries < MAX_RETRIES
):
self._start_auto_refresh_token(
RETRY_INTERVAL ** (self._network_retries * 100) # <-- BUG
)gotrue/_async/gotrue_client.py around line 1065 (same bug):
self._start_auto_refresh_token(
RETRY_INTERVAL ** (self._network_retries * 100) # <-- BUG
)Both the sync and async clients are affected.