khoj-ai/khoj · error · ValueError

Invalid automation id: {automation_id}

Error message

Invalid automation id: {automation_id}

What it means

Raised by ConversationAdapters.get_automation when automation_id is empty/None or does not begin with 'automation_{user.uuid}_'. The prefix check ensures users can only retrieve their own scheduled automations from the APScheduler-backed state.scheduler.

Source

Thrown at src/khoj/database/adapters/__init__.py:2247

        last_run_time = None

        if execution.exists():
            last_run_time = execution.latest("run_time").run_time

        return last_run_time.strftime("%Y-%m-%d %I:%M %p %Z") if last_run_time else None

    @staticmethod
    def get_automations_metadata(user: KhojUser):
        for automation in AutomationAdapters.get_automations(user):
            yield AutomationAdapters.get_automation_metadata(user, automation)

    @staticmethod
    def get_automation(user: KhojUser, automation_id: str) -> Job:
        # Perform validation checks
        # Check if user is allowed to retrieve this automation id
        if is_none_or_empty(automation_id) or not automation_id.startswith(f"automation_{user.uuid}_"):
            raise ValueError(f"Invalid automation id: {automation_id}")
        # Check if automation with this id exist
        automation: Job = state.scheduler.get_job(job_id=automation_id)
        if not automation:
            raise ValueError(f"Invalid automation id: {automation_id}")

        return automation

    @staticmethod
    async def aget_automation(user: KhojUser, automation_id: str) -> Job:
        # Perform validation checks
        # Check if user is allowed to retrieve this automation id
        if is_none_or_empty(automation_id) or not automation_id.startswith(f"automation_{user.uuid}_"):
            raise ValueError(f"Invalid automation id: {automation_id}")
        # Check if automation with this id exist
        automation: Job = await sync_to_async(state.scheduler.get_job)(job_id=automation_id)
        if not automation:
            raise ValueError(f"Invalid automation id: {automation_id}")

View on GitHub (pinned to ae229ca894)

Solutions

  1. Pass the exact id returned when the automation was created for this user.
  2. Validate non-empty and prefix format before calling.
  3. If the automation belongs to another user, use that user's credentials or an admin path.

Example fix

// before
automation = ConversationAdapters.get_automation(user, "")  # ValueError

// after
if is_none_or_empty(automation_id) or not automation_id.startswith(f"automation_{user.uuid}_"):
    return None
automation = ConversationAdapters.get_automation(user, automation_id)
Defensive patterns

Strategy: validation

Validate before calling

from khoj.utils import is_none_or_empty
if is_none_or_empty(automation_id) or not automation_id.startswith(f"automation_{user.uuid}_"):
    return None  # invalid or not owned
automation = ConversationAdapters.get_automation(user, automation_id)

Type guard

def is_valid_automation_id(user, automation_id: str | None) -> bool:
    return bool(automation_id) and automation_id.startswith(f"automation_{user.uuid}_")

Try / catch

try:
    automation = ConversationAdapters.get_automation(user, automation_id)
except ValueError:
    automation = None  # treat as invalid/not-found

Prevention

When it happens

Trigger: Calling get_automation(user, automation_id) with an empty string, None, another user's automation id, or an id that never had the user prefix.

Common situations: Client sends a blank or truncated id from a UI form; sharing automation ids between accounts; typos in manually constructed ids.

Related errors


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