Skip to content

API 429 inventory ​

TOO_MANY_REQUESTS is the published HTTP request-rate code. Existing, more specific refusal codes remain distinct. Nest HTTP domain refusals use DomainErrorFilter; A2A and the separate Bridle transport retain their existing protocol envelopes. Retry-After is an integer number of seconds, copied from details.retryAfterSeconds. It is a backoff instruction, not a guarantee that capacity will be available.

Code / sourceWhat is countedWindow / defaultCounting keyClient action
TOO_MANY_REQUESTS, core HTTP guard, organization credentialAuthenticated service-key HTTP requests across routes and credentials300/minute, 18,000/hour, 432,000/day; configurableVerified organization ID, shared RedisWait Retry-After; ask platform admin to increase Request rate
TOO_MANY_REQUESTS, core HTTP guard, other requestsRequests to each controller handler300/60 seconds by default; REQUEST_RATE_IP_MINUTE; existing route overrides take precedenceIP + controller + handler, in-process Nest throttlerWait Retry-After
Same, credential auth controllerPassword/email operations5/min for slow routes; 20/min for steady routesIP + route, unchanged even if an organization key is suppliedWait Retry-After; do not rotate keys to retry
AGENT_CONCURRENCY_LIMITLive agent turnsCapacity, default 4 (configured 1–64); no time windowAgent ID, database coordinationPoll no faster than Retry-After: 1, or wait for a turn to finish; windowSeconds: null
QUOTA_EXCEEDED, team_rateAgent turnsTeam plan turns/minute, sliding 60 secondsTeam ID, in-processConservative Retry-After: 60
QUOTA_EXCEEDED, team_spendTokens usedSubscription period limitTeam IDRaise budget or wait until details.periodEndsAt; no short Retry-After
QUOTA_EXCEEDED, org_spendUSD pico spend across teamsUTC calendar month, organization budgetOrganization IDRaise/remove budget or wait until details.periodEndsAt; no short Retry-After
BROWSER_VIEW_RATE_LIMITBrowser screenshot requests1 per 2 secondsAgent ID, RedisRetry-After: 2
TOO_MANY_LETTERSConfirmation emails issued3 per sliding hourAccount and link kindConservative Retry-After: 3600; anonymous password-reset requests suppress emails without revealing the account
LLM_RATE_LIMITEDUpstream model provider rate refusal after bounded retriesProvider-specific, not known to this APIProvider credential/modelProvider delay if known, otherwise conservative 60-second backoff; limit/window are null
KNOWLEDGE_INGEST_TOO_EXPENSIVEEstimated document token cost against remaining period budgetCurrent team periodTeam + proposed documentUpload a smaller document or raise the budget; retrying unchanged is not a remedy
TOO_MANY_SUBSCRIPTIONS, partner Bridle subscriberLive subscriptionsCapacity 32WebSocket connectionUnsubscribe before retrying; socket error, no HTTP header
TOO_MANY_REQUESTS, hub subscriberVisitor credential mint requests600 per sliding minuteRemote address, in-processRetry-After: 60; Bridle HTTP transport preserves error and adds code/details
TOO_MANY_REQUESTS, Bridle client repositoryConcurrent in-flight message handlersCapacity 8Runtime connectionWait for work to finish; socket acknowledgment, no HTTP header
SLOW_CONSUMER, Bridle SDKUnconsumed local event queueCapacity 256SDK connectionDrain events/reconnect; client-side error, no HTTP response
A2A JSON-RPC RATE_LIMITED / QUOTA_EXCEEDEDChannel turns or team quotaSliding 60 seconds: 12/visitor and 60/agent; hands-enabled channels 4/visitor and 15/agent; or team period quotaAgent + visitor, and agent; quota by teamPreserve JSON-RPC envelope; transient channel rate uses Retry-After: 60, period quota has no short retry

ARTIFACT_QUOTA_EXCEEDED is 400, not 429. Provider HTTP 429s inside repository adapters are upstream responses, not additional public HTTP contracts. Errors after an SSE response has started travel in stream error frames: HTTP status/headers cannot be rewritten after headers are sent.

Organization counter semantics ​

Only an active, unexpired, non-revoked stored orgk_ credential from the configured partner environment selects the organization bucket. Route authorization still runs and checks scopes, organization and resource access. Invalid keys use the existing IP bucket. Explicit @Throttle route limits always retain their IP behavior. Each Redis window starts on its first admitted request. All three windows are checked atomically; rejected requests neither consume quota nor extend a window. When several windows refuse, the longest remaining wait is returned. Limits are read on every request, so increases apply immediately without resetting usage. Redis/identity-store outages return 503 REQUEST_RATE_UNAVAILABLE, never silently remove the protection. Process restarts retain organization counters in Redis.

October 30 incident ​

The repository establishes possible causes, not which one occurred at 12:52–13:23 UTC or 15:11. Production logs for those requests were not inspected in this task; no historical cause is claimed. Capture response code, details, Retry-After and request correlation ID when investigating another refusal; never log service keys.