PrefectHQ/fastmcp · error · ValueError
Server overloaded, please retry
Error message
Server overloaded, please retry
What it means
Raised by validate_assertion when the server's JTI replay cache has reached _jti_cache_max_size and purging expired entries did not free space. The server deliberately refuses new assertions to prevent a DoS via cache flooding — the message tells the caller to try again later.
Source
Thrown at fastmcp_slim/fastmcp/server/auth/cimd.py:642
# Check if JTI was already used (and hasn't expired from cache)
if jti in self._jti_cache:
cached_exp = self._jti_cache[jti]
if cached_exp > now: # Still valid in cache
raise ValueError(f"Assertion replay detected: jti {jti} already used")
# Expired in cache, can be reused (clean it up)
del self._jti_cache[jti]
# Emergency size limit (shouldn't hit with proper TTL cleanup)
if len(self._jti_cache) >= self._jti_cache_max_size:
self._cleanup_expired_jtis()
# If still over limit after cleanup, reject to prevent DoS
if len(self._jti_cache) >= self._jti_cache_max_size:
self.logger.warning(
"JTI cache at max capacity (%d), possible attack",
self._jti_cache_max_size,
)
raise ValueError("Server overloaded, please retry")
# Add to cache with expiration time
# Use the assertion's exp claim so it stays cached until it would expire anyway
self._jti_cache[jti] = exp
self.logger.debug(
"JWT assertion validated successfully for client %s", client_id
)
return True
def _extract_public_key_from_jwks(self, token: str, jwks: dict) -> str:
"""Extract public key from inline JWKS.
Args:
token: JWT token to extract kid from
jwks: JWKS document containing keys
Returns:View on GitHub (pinned to 1f02114297)
Solutions
- Retry the request after a short backoff — legitimate transient overload usually clears as cached jtis expire
- Increase _jti_cache_max_size if traffic legitimately generates many concurrent assertions
- Investigate logs ('JTI cache at max capacity') for abusive clients and rate-limit them
Example fix
// before validator = CIMDValidator(..., _jti_cache_max_size=1000) # too small for fleet // after validator = CIMDValidator(..., _jti_cache_max_size=100000)
Defensive patterns
Strategy: retry
Try / catch
import time
for attempt in range(3):
try:
validator.validate_assertion(mint_assertion(client_id), client_id, jwks)
break
except ValueError as e:
if "Server overloaded" in str(e):
time.sleep(2 ** attempt)
continue
raise Prevention
- Apply exponential backoff when the server signals overload
- Size _jti_cache_max_size for peak concurrent assertion volume
- Monitor 'JTI cache at max capacity' warnings and rate-limit abusive clients
When it happens
Trigger: A flood of unique-jti assertions (legit high traffic or an attack) filling the cache with entries whose exp values are far in the future; a configuration with a very small _jti_cache_max_size; an attacker spamming assertions to exhaust replay-tracking capacity.
Common situations: High-throughput client fleets sharing one validator instance; mis-tuned cache sizing after deployment; an actual DoS attempt against the token endpoint.
Related errors
- {str(e) from SSRFError/SSRFFetchError}
- CIMD jwks_uri failed SSRF validation: {e}
- Assertion replay detected: jti {jti} already used
- The device authorization request expired
- The device authorization request was denied
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/872f89d3b95437e4.
Report an issue: GitHub.