redis/redis-py · error · TokenRenewalErr
Requested token is expired
Error message
Requested token is expired
What it means
Raised as TokenRenewalErr inside the synchronous _renew_token after force-refreshing the token from the identity provider when token_res.get_token().is_expired() still returns True. This means the freshly acquired token is already expired (e.g. severe clock skew, or the IdP issued an already-expired token). The renewal loop cannot schedule future work against a dead token, so it aborts.
Solutions
- Sync the system clock (NTP/chrony) to eliminate clock skew against the IdP.
- Verify the IdP token TTL and expiration configuration.
- Check network latency between client and IdP; increase TTL if acquisition is slow.
- Register an on_error listener to handle TokenRenewalErr gracefully and trigger re-auth.
Example fix
# before: clock skew makes new token look expired # (no code change; fix the host clock) # after sudo chronyc makestep # or ntpdate / timedatectl set-ntp true
Defensive patterns
Strategy: retry
Try / catch
from redis.auth.err import TokenRenewalErr
try:
manager.start()
except TokenRenewalErr as e:
if "expired" in str(e).lower():
logger.error("newly issued token is expired; check clock sync")
raise Prevention
- Keep system clocks synced via NTP to avoid phantom-expired tokens.
- Register an on_error listener to handle renewal failures with backoff.
When it happens
Trigger: The synchronous token manager's _renew_token calls acquire_token(force_refresh=True), then checks is_expired() on the result; if True, it raises this. Reached during scheduled renewal or the initial token fetch when skip_initial is False.
Common situations: Clock skew between the client and the identity provider so a just-issued token appears expired. The IdP misconfiguration issues tokens with exp in the past. Very short TTLs combined with acquisition latency. System clock not synced via NTP.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/025f42546a7b61e1.
Report an issue: GitHub.
Appendix: source
Thrown at redis/auth/token_manager.py:284
- refresh_before
- (datetime.now(timezone.utc).timestamp() * 1000)
)
def _renew_token(self, skip_initial: bool = False):
"""
Task to renew token from identity provider.
Schedules renewal tasks based on token TTL.
"""
try:
token_res = self.acquire_token(force_refresh=True)
delay = self._calculate_renewal_delay(
token_res.get_token().get_expires_at_ms(),
token_res.get_token().get_received_at_ms(),
)
if token_res.get_token().is_expired():
raise TokenRenewalErr("Requested token is expired")
if self._listener.on_next is None:
logger.warning(
"No registered callback for token renewal task. Renewal cancelled"
)
return
if not skip_initial:
try:
self._listener.on_next(token_res.get_token())
except Exception as e:
raise TokenRenewalErr(e)
if delay <= 0:
return
loop = asyncio.get_running_loop()
self._next_timer = loop.call_later(delay, self._renew_token)View on GitHub (pinned to 6a6b581b48)