khoj-ai/khoj · error · ValidationError

Invalid conversation_log format: {str(e)}

Error message

Invalid conversation_log format: {str(e)}

What it means

Entry.save() calls clean(), which validates that conversation_log['chat'] is a list of pydantic ChatMessageModel objects. Any exception during .get('chat') or model_validate is re-raised as a Django ValidationError.

Source

Thrown at src/khoj/database/models/__init__.py:679

    client = models.ForeignKey(ClientApplication, on_delete=models.CASCADE, default=None, null=True, blank=True)

    # Slug is an app-generated conversation identifier. Need not be unique. Used as display title essentially.
    slug = models.CharField(max_length=200, default=None, null=True, blank=True)

    # The title field is explicitly set by the user.
    title = models.CharField(max_length=500, default=None, null=True, blank=True)
    agent = models.ForeignKey(Agent, on_delete=models.SET_NULL, default=None, null=True, blank=True)
    file_filters = models.JSONField(default=list)
    id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, primary_key=True, db_index=True)

    def clean(self):
        # Validate conversation_log structure
        try:
            messages = self.conversation_log.get("chat", [])
            for msg in messages:
                ChatMessageModel.model_validate(msg)
        except Exception as e:
            raise ValidationError(f"Invalid conversation_log format: {str(e)}")

    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)

    @property
    def messages(self) -> List[ChatMessageModel]:
        """Type-hinted accessor for conversation messages"""
        validated_messages = []
        for msg in self.conversation_log.get("chat", []):
            try:
                # Clean up inferred queries if they contain None
                if msg.get("intent") and msg["intent"].get("inferred_queries"):
                    msg["intent"]["inferred-queries"] = [
                        q for q in msg["intent"]["inferred_queries"] if q is not None and isinstance(q, str)
                    ]
                msg["message"] = str(msg.get("message", ""))
                validated_messages.append(ChatMessageModel.model_validate(msg))

View on GitHub (pinned to ae229ca894)

Solutions

  1. Inspect str(e) in the message to see which field failed pydantic validation.
  2. Build conversation_log entries with ChatMessageModel.model_validate(msg) (or construct model instances and use .model_dump()) before assigning.
  3. If migrating old data, write a normalization step mapping legacy keys to the current schema.

Example fix

# before
chat.conversation_log = {"chat": [{"role": "user", "text": "hi"}]}  # wrong keys
chat.save()  # ValidationError

# after
from khoj.database.models import ChatMessage
msg = ChatMessage(role="user", content="hi")  # pydantic model
chat.conversation_log = {"chat": [msg.model_dump()]}
chat.save()
Defensive patterns

Strategy: validation

Validate before calling

from pydantic import ValidationError as PydanticError
from khoj.database.models import ChatMessage

def valid_conversation_log(log: dict) -> bool:
    try:
        for msg in log.get("chat", []):
            ChatMessage.model_validate(msg)
        return True
    except PydanticError:
        return False

if not valid_conversation_log(chat.conversation_log):
    raise HTTPException(400, "bad conversation_log")
chat.save()

Type guard

def is_valid_conversation_log(log) -> bool:
    return isinstance(log, dict) and isinstance(log.get("chat"), list)

Try / catch

from django.core.exceptions import ValidationError
try:
    chat.save()
except ValidationError as e:
    if "Invalid conversation_log format" in str(e):
        # log details, quarantine row, or normalize messages
        ...
    raise

Prevention

When it happens

Trigger: Saving a Chat model object whose conversation_log lacks a 'chat' key, has non-list 'chat', or contains message dicts missing/typoing required ChatMessageModel fields (e.g. 'message' key absent).

Common situations: Hand-built or migrated conversation_log dicts; schema drift after upgrading khoj's ChatMessageModel; third-party code writing raw dicts with wrong keys.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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