zylon-ai/private-gpt · error · RateLimitExceeded
Brave Search API rate limit exceeded: {error_message}
Error message
Brave Search API rate limit exceeded: {error_message} What it means
RateLimitExceeded raised when the Brave Search API responds HTTP 429. The provider extracts the error detail from the JSON body (response_data['error']) and raises this typed exception so callers can distinguish transient throttling from auth or quota problems. Logged at debug level before raising.
Source
Thrown at private_gpt/components/web/web_search/providers/brave.py:240
def _check_response(
self, response: ClientResponse, response_data: dict[str, Any]
) -> None:
quota_header = response.headers.get("x-ratelimit-remaining")
if quota_header is not None and quota_header.strip() == "0":
raise QuotaConsumed(
"Brave Search API quota exhausted (x-ratelimit-remaining=0)"
)
status_code = response.status
if status_code < 400:
return
error = response_data.get("error", "Unknown error")
error_message = self._extract_error_message(error)
if status_code == 429:
logger.debug(f"Brave Search API rate limit exceeded: {error_message}")
raise RateLimitExceeded(
f"Brave Search API rate limit exceeded: {error_message}"
)
elif status_code == 400:
raise ValueError(f"Brave Search API invalid token ({error_message})")
elif status_code >= 500:
raise Exception(f"Brave Search API server error: {error_message}")
else:
raise Exception(f"Brave Search API error ({status_code}): {error_message}")
def _build_request_params(
self,
query: str,
num_links: int,
offset: int,
result_filter: str,
safesearch: bool,
freshness: str | None,
spellcheck: bool,View on GitHub (pinned to 4a030776a3)
Solutions
- Retry with exponential backoff honoring Retry-After if present.
- Increase brave.rate_limit (minimum seconds between requests) to match the plan's allowance.
- Reduce concurrency (web_search.num_concurrent_consumers) and enable web_search.cached.
- Upgrade the Brave plan if sustained traffic needs more throughput.
Example fix
# before
resp = await provider.make_query(q, n)
# after
for attempt in range(3):
try:
resp = await provider.make_query(q, n)
break
except RateLimitExceeded:
await asyncio.sleep(2 ** attempt) Defensive patterns
Strategy: retry
Type guard
def is_rate_limited(exc: BaseException) -> bool:
return type(exc).__name__ == 'RateLimitExceeded' Try / catch
from private_gpt.components.web.web_search.providers.brave import RateLimitExceeded
for delay in (1, 2, 4):
try:
results = await provider.make_query(q, num_links)
break
except RateLimitExceeded:
await asyncio.sleep(delay)
else:
raise Prevention
- Space requests at least brave.rate_limit seconds apart via a shared limiter.
- Cap web_search.num_concurrent_consumers to your plan's throughput.
- Retry only 429/QuotaConsumed with backoff; never hammer through auth errors.
When it happens
Trigger: Exceeding requests-per-second on the key; retry storms where a slow request is re-fired immediately; parallel consumers each holding their own Brave session bypassing the rate_limit spacing.
Common situations: Load tests against the search endpoint; multiple private-gpt replicas sharing one key without coordination; free-tier key under bursty chat traffic.
Related errors
- Brave Search API quota exhausted (x-ratelimit-remaining=0)
- Brave Search API server error: {error_message}
- Brave Search API error ({status_code}): {error_message}
- Model server is not available or request failed.
- Invalid page token
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/f22a10237ffc5129.
Report an issue: GitHub.