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

  1. Retry the request after a short backoff — legitimate transient overload usually clears as cached jtis expire
  2. Increase _jti_cache_max_size if traffic legitimately generates many concurrent assertions
  3. 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

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


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/872f89d3b95437e4. Report an issue: GitHub.