different-ai/openwork · warning · TooManyRequestsError
MCP_OAUTH_TOO_MANY_REQUESTS
MCP_OAUTH_TOO_MANY_REQUESTS
Error message
Wait for the provider rate limit to reset, then retry with bounded backoff.
What it means
This diagnostic code is emitted when the OAuth error name is TooManyRequestsError, i.e. the provider's authorization server returned HTTP 429 / a rate-limit error during the OAuth flow. The classifier marks it retryable (oauth_provider_throttled) but assigns the fix to the provider administrator, since the provider's limits control when retries will succeed.
Source
Thrown at ee/apps/den-api/src/capability-sources/external-mcp-diagnostics.ts:1338
actionOwner: "provider_admin",
operatorAction: "Configure the authorization server to issue a token type supported by the MCP client and resource.",
}
}
if (name === "MethodNotAllowedError") {
return {
phase: fallbackPhase,
category: "oauth_method_not_allowed",
code: "MCP_OAUTH_METHOD_NOT_ALLOWED",
retryable: false,
actionOwner: "provider_admin",
operatorAction: "Verify the provider OAuth endpoint path and its supported HTTP method.",
}
}
if (name === "TooManyRequestsError") {
return {
phase: fallbackPhase,
category: "oauth_provider_throttled",
code: "MCP_OAUTH_TOO_MANY_REQUESTS",
retryable: true,
actionOwner: "provider_admin",
operatorAction: "Wait for the provider rate limit to reset, then retry with bounded backoff.",
}
}
if (name === "AccessDeniedError") {
return {
phase: "AUTH_USER_OR_WORKLOAD",
category: "oauth_access_denied",
code: "MCP_OAUTH_ACCESS_DENIED",
retryable: false,
actionOwner: "member",
operatorAction: "Restart authorization and grant consent; if policy blocks consent, contact the provider administrator.",
}
}
if (name === "InvalidRequestError" || name === "UnsupportedGrantTypeError" || name === "UnsupportedResponseTypeError") {
return {
phase: fallbackPhase,View on GitHub (pinned to 2b7df46e8a)
Solutions
- Stop retrying immediately and wait for the provider rate-limit window to reset (check Retry-After if present).
- Retry the OAuth flow with bounded exponential backoff and jitter instead of fixed tight loops.
- Ask the provider admin to raise the rate limit or issue a dedicated client quota for your integration.
- Reduce OAuth call frequency: cache tokens until near expiry and avoid redundant refreshes.
Example fix
// before: fixed tight retry
for (;;) { await refresh(); }
// after: bounded backoff honoring 429
if (res.status === 429) { await sleep(Math.min(cap, base * 2 ** attempt) + jitter(attempt)); continue; } Defensive patterns
Strategy: retry
Validate before calling
const probe = await fetch(authorizeUrl, { method: 'HEAD' });
if (probe.status === 429) throw new Error(`Provider throttled, retry after ${probe.headers.get('retry-after') ?? 'window reset'}`); Type guard
function isTooManyRequests(e: unknown): boolean {
return typeof e === 'object' && e !== null && (e as { name?: string }).name === 'TooManyRequestsError';
} Try / catch
try { await startOAuth(server); } catch (e) {
if (isTooManyRequests(e)) { await backoffRetry(startOAuth, [server], { baseMs: 1000, capMs: 60000, maxAttempts: 5 }); return; }
throw e;
} Prevention
- Cache OAuth tokens until near expiry; never refresh in a loop
- Add jittered exponential backoff to every OAuth call
- Pace bulk user onboarding to stay under per-IP/per-client quotas
- Watch Retry-After headers and surface 429s instead of hot-retrying
When it happens
Trigger: OAuth authorize/token/refresh calls to an external MCP provider exceed its request quota: repeated auth attempts in a loop, many concurrent users authenticating, refresh tokens being exchanged too frequently, or the provider throttling per-IP/per-client traffic during discovery.
Common situations: Shared egress IP (CI, proxy, office NAT) exhausting the provider's per-IP quota; an automated retry loop hammering the token endpoint without backoff; provider-side throttling recently tightened; burst of new MCP server connections after a deploy.
Related errors
- MCP_PROVIDER_HTTP_429
- MCP_HTTP_429
- `${t("providers.no_oauth_prefix")} ${resolved}. ${t("provide
- `${t("providers.not_oauth_flow_prefix")} ${resolved}.`
- t("providers.oauth_method_required")
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/07177b69e2ecd0c2.
Report an issue: GitHub.