{"record":{"id":"65466dec9fbb2f26","repo":"khoj-ai/khoj","slug":"common-message-prefix-you-can-subscribe-to-incre","errorCode":null,"errorMessage":"{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}.","messagePattern":"(.+?) You can subscribe to increase your usage limit via \\[your settings\\]\\(https://app\\.khoj\\.dev/settings\\) or we can continue our conversation (.+?)\\.","errorType":"http","errorClass":"HTTPException","httpStatus":429,"severity":"warning","filePath":"src/khoj/routers/helpers.py","lineNumber":2199,"sourceCode":"            )\n            raise HTTPException(\n                status_code=429,\n                detail=f\"{common_message_prefix} But let's chat more {next_window}?\",\n            )\n        if not subscribed and count_requests >= self.requests:\n            if self.requests >= self.subscribed_requests:\n                logger.info(\n                    f\"Rate limit ({self.slug}): {count_requests}/{self.subscribed_requests} requests not allowed in {self.window} seconds for user: {user}.\"\n                )\n                raise HTTPException(\n                    status_code=429,\n                    detail=f\"{common_message_prefix} But let's chat more {next_window}?\",\n                )\n\n            logger.info(\n                f\"Rate limit ({self.slug}): {count_requests}/{self.requests} requests not allowed in {self.window} seconds for user: {user}.\"\n            )\n            raise HTTPException(\n                status_code=429,\n                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}.\",\n            )\n\n        # Add the current request to the cache\n        await UserRequests.objects.acreate(user=user, slug=self.slug)\n\n\nclass ApiImageRateLimiter:\n    def __init__(self, max_images: int = 10, max_combined_size_mb: float = 10):\n        self.max_images = max_images\n        self.max_combined_size_mb = max_combined_size_mb\n\n    def __call__(self, request: Request, body: ChatRequestBody):\n        if state.billing_enabled is False:\n            return\n\n        # Rate limiting is disabled if user unauthenticated.","sourceCodeStart":2181,"sourceCodeEnd":2217,"githubUrl":"https://github.com/khoj-ai/khoj/blob/ae229ca894c0b80ad84664afcfdde523b5e87057/src/khoj/routers/helpers.py#L2181-L2217","documentation":"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.","triggerScenarios":"Exceeding the free `self.requests` quota over the WebSocket within the window, with a limiter whose subscribed quota is higher.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    await ws.send(frame)\nexcept (WebSocketException, HTTPException) as e:\n    if getattr(e, 'status_code', None) == 429:\n        notify_user_upgrade_or_wait()\n    else:\n        raise","preventionTips":["Track remaining free quota client-side per session","Upgrade the account for production integrations","Avoid auto-retry loops that burn quota"],"tags":["rate-limit","http-429","websocket","khoj","subscription"],"backgroundTag":"http-429-rate-limit-exceeded","analyzedSha":"ae229ca894c0b80ad84664afcfdde523b5e87057","analyzedAt":"2026-08-27T03:32:41.843Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}