khoj-ai/khoj · warning · HTTPException

Those are way too many images for me! I can handle up to {se

Error message

Those are way too many images for me! I can handle up to {self.max_images} images per message.

What it means

A 429 raised by the per-message image-count limiter when a chat request body contains more images than `max_images` allows. It is a payload validation failure dressed as a rate limit, hit in the synchronous __call__ dependency of the chat endpoint.

Source

Thrown at src/khoj/routers/helpers.py:2228

        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.
        # Other systems handle authentication
        if not request.user.is_authenticated:
            return

        if not body.images:
            return

        # Check number of images
        if len(body.images) > self.max_images:
            logger.info(f"Rate limit: {len(body.images)}/{self.max_images} images not allowed per message.")
            raise HTTPException(
                status_code=429,
                detail=f"Those are way too many images for me! I can handle up to {self.max_images} images per message.",
            )

        # Check total size of images
        total_size_mb = 0.0
        for image in body.images:
            # Unquote the image in case it's URL encoded
            image = unquote(image)
            # Assuming the image is a base64 encoded string
            # Remove the data:image/jpeg;base64, part if present
            if "," in image:
                image = image.split(",", 1)[1]

            # Decode base64 to get the actual size
            image_bytes = base64.b64decode(image)
            total_size_mb += len(image_bytes) / (1024 * 1024)  # Convert bytes to MB

View on GitHub (pinned to ae229ca894)

Solutions

  1. Split the request into multiple messages each with at most max_images images
  2. Check the configured max_images value for the deployment and stay under it
  3. Drop or downselect unnecessary images before sending
  4. Fix client logic that accumulates images across turns

Example fix

// before
await client.chat({ q: prompt, images: allImages })  // 20 images
// after
for (const chunk of chunkAll(allImages, 6)) {
  await client.chat({ q: prompt, images: chunk })
}
Defensive patterns

Strategy: validation

Validate before calling

MAX_IMAGES = 6  # mirror server config
if len(images) > MAX_IMAGES:
    raise ValueError(f'Too many images: {len(images)} > {MAX_IMAGES}')

Type guard

def is_valid_image_count(images: list[str] | None, max_images: int = 6) -> bool:
    return not images or len(images) <= max_images

Try / catch

try:
    resp = await client.post('/api/chat', json=body)
except HTTPStatusError as e:
    if e.response.status_code == 429 and 'too many images' in e.response.text:
        body['images'] = body['images'][:max_images]
        resp = await client.post('/api/chat', json=body)
    else:
        raise

Prevention

When it happens

Trigger: POSTing to /api/chat (or any endpoint using the image rate limiter) with `body.images` containing more than `self.max_images` base64 images in a single message.

Common situations: Clients batching whole photo albums into one message; frontend not chunking multi-image uploads; a bug concatenating image lists across messages.

Related errors


AI-assisted analysis of khoj-ai/khoj@ae229ca894 (2026-08-27). Data as JSON: /api/errors/4e4ed39b578eff11. Report an issue: GitHub.