Genace

Video generation API 429 errors: distinguish rate limits from active-job limits

Video generation API 429 errors have two different causes in Genace. RATE_LIMIT_EXCEEDED means the API key exceeded its request window. CONCURRENCY_LIMIT_EXCEEDED means the user already has too many active jobs. Both use HTTP 429, but waiting for the wrong resource can leave your application stuck in a retry loop.

Read error.code and error.type before choosing recovery. Preserve the response body in a sanitized diagnostic record, together with the operation you attempted. A throttled submission and a throttled status read need different scheduling decisions.

Route the response by code

function routeThrottle(body) {
  switch (body.error?.code) {
    case 'RATE_LIMIT_EXCEEDED':
      return 'pause shared request dispatch and reduce polling';
    case 'CONCURRENCY_LIMIT_EXCEEDED':
      return 'wait for an existing active job to become terminal';
    default:
      return 'record the response and use bounded conservative backoff';
  }
}

This small function is intended for an HTTP response your client has already read. It does not retry or generate anything. Keeping classification separate from dispatch makes it easier to verify that your retry policy cannot accidentally create more work.

Diagnose request pressure

The gateway applies authentication, then a request-rate check, then the active-job check where applicable. Request events are counted per API key in a sixty-second sliding window. The implementation records the current request before counting, including requests that are rejected. Rapidly retrying every rejected request therefore adds pressure instead of helping the window clear.

The current job GET route has a sixty-RPM override and skips active-generation concurrency checks. The SSE route uses thirty RPM and also skips the concurrency check. These overrides do not mean requests are free from rate limiting. Multiple workers sharing a key still contribute traffic to that key’s request history.

Measure calls by operation and key alias. A noisy health checker or several browser tabs may be the actual source of throttling, even if the generation worker itself submits slowly. Never print the raw key in your logs.

Diagnose occupied capacity

The concurrency checker counts queued and running jobs for the user. Polling more often cannot create a new slot. Continue collecting existing work and delay new submissions until a terminal snapshot is saved. Switching keys for the same user does not bypass this user-level limit.

Common mistakes include treating every 429 as an upstream model failure, retrying invalid submissions after a delay, and launching fallback models when the real problem is account capacity. A fallback submission uses the same gateway admission checks and can encounter the same rejection.

Verification checklist

Feed both documented error codes into your dispatcher and verify that they choose different actions. Simulate several collectors using one key and confirm that a shared pause reduces traffic. Check that active-job saturation pauses creation while preserving collection of existing identifiers.

For the underlying mechanisms, see concurrency, retry backoff, and polling.

Continue with production operations

Where these facts come from

  • codebase: src/ai/api/rate-limit.ts
  • codebase: src/ai/api/concurrency.ts
  • codebase: src/ai/api/wrap.ts
  • Editorial keyword hypothesis; search volume not measured