{"record":{"id":"57ba69fbdbbe013a","repo":"xtekky/gpt4free","slug":"ratelimit-exceeded","errorCode":null,"errorMessage":"Ratelimit Exceeded!","messagePattern":"Ratelimit Exceeded!","errorType":"exception","errorClass":"RateLimitError","httpStatus":null,"severity":"error","filePath":"g4f/Provider/needs_auth/Airforce.py","lineNumber":32,"sourceCode":"    active_by_default = True\n    use_image_size = True\n    default_model = \"gpt-4o-mini\"\n\n    @classmethod\n    async def create_async_generator(\n        cls, model: str, messages: Messages = None, **kwargs\n    ) -> AsyncResult:\n        ratelimit_message = \"Ratelimit Exceeded!\"\n        buffer = \"\"\n        async for chunk in super().create_async_generator(\n            model=model, messages=messages, **kwargs\n        ):\n            if not isinstance(chunk, str):\n                yield chunk\n                continue\n            buffer += chunk\n            if ratelimit_message in buffer:\n                raise RateLimitError(ratelimit_message)\n            if ratelimit_message.startswith(buffer):\n                continue\n            yield buffer\n            buffer = \"\"\n","sourceCodeStart":14,"sourceCodeEnd":37,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/needs_auth/Airforce.py#L14-L37","documentation":"RateLimitError raised by the Airforce provider while relaying the upstream OpenAI-compatible stream: it buffers incoming string chunks and checks whether the accumulated text contains 'Ratelimit Exceeded!' — api.airforce signals throttling by streaming that literal string instead of an HTTP 429. Because the check matches on the message appearing mid-stream, the error fires the moment the phrase is complete; partial prefixes of it are held back instead of yielded.","triggerScenarios":"Calling any Airforce model after exceeding api.airforce's request-rate or token quota: the HTTP response is 200 and the SSE stream opens normally, but the delta content is the literal 'Ratelimit Exceeded!' string; bursty parallel requests from one IP; free-tier daily caps.","commonSituations":"Hammering api.airforce in a loop or with concurrent workers; shared/datacenter IPs already throttled; free-tier quota exhaustion mid-session.","solutions":["Back off and retry after a delay (start ~30–60s) — the throttle is usually time-window based.","Reduce request concurrency/frequency against api.airforce.","Get an api_key from the Airforce panel (login_url https://panel.api.airforce/dashboard) for higher limits.","Catch RateLimitError in your loop and switch to a fallback provider for the duration of the throttle."],"exampleFix":"# before\nfor chunk in await Airforce.create_async_generator(model=model, messages=messages):\n    print(chunk, end=\"\")\n\n# after\nfrom g4f.errors import RateLimitError\ntry:\n    async for chunk in Airforce.create_async_generator(model=model, messages=messages):\n        print(chunk, end=\"\")\nexcept RateLimitError:\n    await asyncio.sleep(60)  # then retry or fail over","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"from g4f.errors import RateLimitError\nfor attempt in range(5):\n    try:\n        async for chunk in Airforce.create_async_generator(model=model, messages=messages):\n            ...\n        break\n    except RateLimitError:\n        await asyncio.sleep(2 ** attempt * 15)  # exponential backoff, then fail over","preventionTips":["Throttle request rate and concurrency against api.airforce.","Use exponential backoff on RateLimitError, not immediate retries.","Register an api_key at the Airforce panel for higher limits; keep a fallback provider."],"tags":["rate-limit","airforce","streaming","throttle"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}