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
- Pass the exact id returned when the automation was created for this user.
- Validate non-empty and prefix format before calling.
- 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
- Validate id presence and ownership prefix at the API boundary.
- Keep automation ids opaque to clients; look them up per user.
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
- Invalid conversation_log format: {str(e)}
- An Entry cannot be associated with both a user and an agent.
- A public Agent with the name {instance.name} already exists.
- A private Agent with the name {instance.name} already exists
- Invalid conversation settings. Configure some chat model on
AI-assisted analysis of khoj-ai/khoj@ae229ca894 (2026-08-27).
Data as JSON: /api/errors/0efff154dce7750d.
Report an issue: GitHub.