khoj-ai/khoj · warning · HTTPException
{common_message_prefix} You can subscribe to increase your u
Error message
{common_message_prefix} You can subscribe to increase your usage limit via [your settings](https://app.khoj.dev/settings) or we can continue our conversation {next_window}. What it means
WebSocket rate-limit 429 for an UNSUBSCRIBED user where subscribing would raise the cap (free limit < subscribed limit). The message advertises the settings/subscription page as the remedy.
Source
Thrown at src/khoj/routers/helpers.py:2199
)
raise HTTPException(
status_code=429,
detail=f"{common_message_prefix} But let's chat more {next_window}?",
)
if not subscribed and count_requests >= self.requests:
if self.requests >= self.subscribed_requests:
logger.info(
f"Rate limit ({self.slug}): {count_requests}/{self.subscribed_requests} requests not allowed in {self.window} seconds for user: {user}."
)
raise HTTPException(
status_code=429,
detail=f"{common_message_prefix} But let's chat more {next_window}?",
)
logger.info(
f"Rate limit ({self.slug}): {count_requests}/{self.requests} requests not allowed in {self.window} seconds for user: {user}."
)
raise HTTPException(
status_code=429,
detail=f"{common_message_prefix} You can subscribe to increase your usage limit via [your settings](https://app.khoj.dev/settings) or we can continue our conversation {next_window}.",
)
# Add the current request to the cache
await UserRequests.objects.acreate(user=user, slug=self.slug)
class ApiImageRateLimiter:
def __init__(self, max_images: int = 10, max_combined_size_mb: float = 10):
self.max_images = max_images
self.max_combined_size_mb = max_combined_size_mb
def __call__(self, request: Request, body: ChatRequestBody):
if state.billing_enabled is False:
return
# Rate limiting is disabled if user unauthenticated.View on GitHub (pinned to ae229ca894)
Solutions
- Subscribe at https://app.khoj.dev/settings to raise the quota
- Wait for the window reset or reduce send frequency
- Implement client-side send throttling with 429 awareness
- Audit the client for redundant/retrying sends
Defensive patterns
Strategy: fallback
Try / catch
try:
await ws.send(frame)
except (WebSocketException, HTTPException) as e:
if getattr(e, 'status_code', None) == 429:
notify_user_upgrade_or_wait()
else:
raise Prevention
- Track remaining free quota client-side per session
- Upgrade the account for production integrations
- Avoid auto-retry loops that burn quota
When it happens
Trigger: Exceeding the free `self.requests` quota over the WebSocket within the window, with a limiter whose subscribed quota is higher.
Common situations: Free-tier users of the hosted WebSocket chat hitting daily caps; long-running agents or integrations on a free account; users unaware their client auto-retries and burns quota.
Related errors
- I'm glad you're enjoying interacting with me! You've unfortu
- {common_message_prefix} But let's chat more {next_window}?
- Those are way too many images for me! I can handle up to {se
- I'm glad you're enjoying interacting with me! You've unfortu
- Those images are way too large for me! I can handle up to {s
AI-assisted analysis of khoj-ai/khoj@ae229ca894 (2026-08-27).
Data as JSON: /api/errors/65466dec9fbb2f26.
Report an issue: GitHub.