alibaba/page-agent · warning · InvokeError

RATE_LIMIT

RATE_LIMIT

Error message

Rate limit exceeded: ${errorMessage}

What it means

The endpoint returned HTTP 429 — you've exceeded a rate limit or quota (requests per minute, tokens per minute, or billing cap). The provider's error message and body are attached so you can see which limit was hit.

Source

Thrown at packages/llms/src/OpenAIClient.ts:109

		// 3. Handle HTTP errors
		if (!response.ok) {
			let errorData: any
			try {
				errorData = await response.json()
			} catch (error) {
				if ((error as any)?.name === 'AbortError') throw error
			}
			const errorMessage = errorData?.error?.message || response.statusText

			if (response.status === 401 || response.status === 403) {
				throw new InvokeError(
					InvokeErrorTypes.AUTH_ERROR,
					`Authentication failed: ${errorMessage}`,
					errorData
				)
			}
			if (response.status === 429) {
				throw new InvokeError(
					InvokeErrorTypes.RATE_LIMIT,
					`Rate limit exceeded: ${errorMessage}`,
					errorData
				)
			}
			if (response.status >= 500) {
				throw new InvokeError(
					InvokeErrorTypes.SERVER_ERROR,
					`Server error: ${errorMessage}`,
					errorData
				)
			}
			throw new InvokeError(
				InvokeErrorTypes.UNKNOWN,
				`HTTP ${response.status}: ${errorMessage}`,
				errorData
			)
		}

View on GitHub (pinned to d02db1ee7c)

Solutions

  1. Add exponential backoff retry on RATE_LIMIT errors (respect Retry-After header if present)
  2. Reduce request frequency or concurrency in the calling loop
  3. Check the provider dashboard for which limit (RPM/TPM/billing) is hit and request a raise or top up billing
  4. Switch to a higher-limit model tier or distribute across keys/projects

Example fix

// before
const result = await llm.invoke(request)

// after
async function invokeWithBackoff(llm, request, retries = 3) {
  for (let i = 0; i <= retries; i++) {
    try { return await llm.invoke(request) }
    catch (e) {
      if (e.code !== 'RATE_LIMIT' || i === retries) throw e
      await new Promise(r => setTimeout(r, 2 ** i * 1000))
    }
  }
}
Defensive patterns

Strategy: retry

Validate before calling

// throttle before invoking: simple token bucket
if (now - lastCallTime < minIntervalMs) await sleep(minIntervalMs - (now - lastCallTime))
await client.invoke(req)

Type guard

const isRateLimitError = (e: unknown): e is InvokeError =>
  e instanceof InvokeError && e.code === 'RATE_LIMIT'

Try / catch

for (let attempt = 0; ; attempt++) {
  try { return await client.invoke(req) }
  catch (e) {
    if (!isRateLimitError(e) || attempt >= 5) throw e
    await sleep(2 ** attempt * 500)
  }
}

Prevention

When it happens

Trigger: invoke() bursts requests faster than the account/provider RPM/TPM allows; shared free-tier quota exhausted; concurrent agent loops firing many chat/completions calls; a specific model having a stricter tier limit.

Common situations: Agentic loops with no throttling; free-tier keys (strict RPM); retry storms amplifying traffic; billing quota exhausted; multiple environments sharing one key.

Related errors


AI-assisted analysis of alibaba/page-agent@d02db1ee7c (2026-08-28). Data as JSON: /api/errors/e1444c252412306c. Report an issue: GitHub.