ruvnet/ruflo · error · RateLimitError

RATE_LIMIT

RATE_LIMIT

Error message

${message}

What it means

CohereProvider maps HTTP 429 to RateLimitError (retryable). Cohere returns 429 when you exceed organization rate limits (requests or tokens per minute) or trial-tier caps. Note that this mapping passes retryAfter as undefined - the library does not extract Cohere's retry-after header here, so callers must apply their own backoff.

Source

Thrown at v3/@claude-flow/providers/src/cohere-provider.ts:411

  }

  private async handleErrorResponse(response: Response): Promise<never> {
    const errorText = await response.text();
    let errorData: { message?: string };

    try {
      errorData = JSON.parse(errorText);
    } catch {
      errorData = { message: errorText };
    }

    const message = errorData.message || 'Unknown error';

    switch (response.status) {
      case 401:
        throw new AuthenticationError(message, 'cohere', errorData);
      case 429:
        throw new RateLimitError(message, 'cohere', undefined, errorData);
      default:
        throw new LLMProviderError(
          message,
          `COHERE_${response.status}`,
          'cohere',
          response.status,
          response.status >= 500,
          errorData
        );
    }
  }
}

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Retry on RateLimitError with exponential backoff and jitter (start ~1 s, double, cap ~60 s)
  2. Reduce concurrency (e.g. p-limit) and batch size to stay under RPM/TPM
  3. Inspect the Cohere dashboard for current limits and upgrade the plan if throttling is sustained
  4. Read error.details for Cohere's response body and honor any retry-after information it carries

Example fix

// before
const res = await provider.complete(req); // 429 propagates as RateLimitError

// after - retry with backoff on RateLimitError
async function completeWithBackoff(provider, req, tries = 5) {
  for (let i = 0; ; i++) {
    try { return await provider.complete(req); }
    catch (e) {
      if (e instanceof RateLimitError && i < tries - 1) {
        await new Promise(r => setTimeout(r, Math.min(60_000, 2 ** i * 1000)));
        continue;
      }
      throw e;
    }
  }
}
Defensive patterns

Strategy: retry

Type guard

import { RateLimitError } from './types.js';
function isCohereRateLimit(e: unknown): e is RateLimitError {
  return e instanceof RateLimitError && e.provider === 'cohere';
}

Try / catch

for (let attempt = 0; ; attempt++) {
  try {
    return await provider.complete(req);
  } catch (e) {
    if (isCohereRateLimit(e) && attempt < 5) {
      // this mapping leaves retryAfter undefined - choose your own backoff
      await new Promise(r => setTimeout(r, Math.min(60_000, 2 ** attempt * 1000) + Math.random() * 500));
      continue;
    }
    throw e;
  }
}

Prevention

When it happens

Trigger: A burst of provider.complete() calls exceeding the plan's RPM/TPM; many parallel completions from a fan-out workflow; load testing against a trial key.

Common situations: Concurrent batch generation without a concurrency limit; production traffic spike; plan too small for sustained throughput.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/8908ad866440431f. Report an issue: GitHub.