khoj-ai/khoj · warning · HTTPException
{common_message_prefix} But let's chat more {next_window}?
Error message
{common_message_prefix} But let's chat more {next_window}? What it means
A 429 raised in the WebSocket variant of the request rate limiter (check_websocket) when a SUBSCRIBED user exceeds the higher subscribed quota within the window. Because the user already pays, no upgrade is offered — only waiting until `next_window`.
Source
Thrown at src/khoj/routers/helpers.py:2182
if not websocket.scope.get("user") or not websocket.scope["user"].is_authenticated:
return
user: KhojUser = websocket.scope["user"].object
subscribed = has_required_scope(websocket, ["premium"])
current_window = "today" if self.window == 60 * 60 * 24 else "now"
next_window = "tomorrow" if self.window == 60 * 60 * 24 else "in a bit"
common_message_prefix = f"I'm glad you're enjoying interacting with me! You've unfortunately exceeded your usage limit for {current_window}."
# Remove requests outside of the time window
cutoff = django_timezone.now() - timedelta(seconds=self.window)
count_requests = await UserRequests.objects.filter(user=user, created_at__gte=cutoff, slug=self.slug).acount()
# Check if the user has exceeded the rate limit
if subscribed and count_requests >= self.subscribed_requests:
logger.info(
f"Rate limit ({self.slug}): {count_requests}/{self.subscribed_requests} requests not allowed in {self.window} seconds for subscribed user: {user}."
)
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,View on GitHub (pinned to ae229ca894)
Solutions
- Add exponential backoff / cooldown in the WebSocket client after a 429
- Reduce message frequency or batch prompts
- Verify no client-side bug is re-sending messages (check server log for the limiter slug and counts)
- Wait for the window to reset (next_window hints when)
Defensive patterns
Strategy: retry
Try / catch
try:
await ws.send(frame)
except (WebSocketException, HTTPException) as e:
if getattr(e, 'status_code', None) == 429:
await schedule_resend_after_window()
else:
raise Prevention
- Rate-limit WebSocket sends client-side below the subscribed quota
- Debounce burst UI actions before sending
- Monitor for 429 frames and pause the sender
When it happens
Trigger: Opening/sending on the WebSocket chat endpoint more than `subscribed_requests` times within `self.window` seconds while authenticated as a subscribed user.
Common situations: Heavy programmatic WebSocket clients or agents sending bursts of messages; automated tests reusing one subscribed account; a stuck client retransmitting in a loop.
Related errors
- {common_message_prefix} You can subscribe to increase your u
- I'm glad you're enjoying interacting with me! You've unfortu
- 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/8cfec9914cbc39b0.
Report an issue: GitHub.