{"record":{"id":"0efff154dce7750d","repo":"khoj-ai/khoj","slug":"invalid-automation-id-automation-id-0efff1","errorCode":null,"errorMessage":"Invalid automation id: {automation_id}","messagePattern":"Invalid automation id: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/khoj/database/adapters/__init__.py","lineNumber":2247,"sourceCode":"\n        last_run_time = None\n\n        if execution.exists():\n            last_run_time = execution.latest(\"run_time\").run_time\n\n        return last_run_time.strftime(\"%Y-%m-%d %I:%M %p %Z\") if last_run_time else None\n\n    @staticmethod\n    def get_automations_metadata(user: KhojUser):\n        for automation in AutomationAdapters.get_automations(user):\n            yield AutomationAdapters.get_automation_metadata(user, automation)\n\n    @staticmethod\n    def get_automation(user: KhojUser, automation_id: str) -> Job:\n        # Perform validation checks\n        # Check if user is allowed to retrieve this automation id\n        if is_none_or_empty(automation_id) or not automation_id.startswith(f\"automation_{user.uuid}_\"):\n            raise ValueError(f\"Invalid automation id: {automation_id}\")\n        # Check if automation with this id exist\n        automation: Job = state.scheduler.get_job(job_id=automation_id)\n        if not automation:\n            raise ValueError(f\"Invalid automation id: {automation_id}\")\n\n        return automation\n\n    @staticmethod\n    async def aget_automation(user: KhojUser, automation_id: str) -> Job:\n        # Perform validation checks\n        # Check if user is allowed to retrieve this automation id\n        if is_none_or_empty(automation_id) or not automation_id.startswith(f\"automation_{user.uuid}_\"):\n            raise ValueError(f\"Invalid automation id: {automation_id}\")\n        # Check if automation with this id exist\n        automation: Job = await sync_to_async(state.scheduler.get_job)(job_id=automation_id)\n        if not automation:\n            raise ValueError(f\"Invalid automation id: {automation_id}\")\n","sourceCodeStart":2229,"sourceCodeEnd":2265,"githubUrl":"https://github.com/khoj-ai/khoj/blob/ae229ca894c0b80ad84664afcfdde523b5e87057/src/khoj/database/adapters/__init__.py#L2229-L2265","documentation":"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.","triggerScenarios":"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.","commonSituations":"Client sends a blank or truncated id from a UI form; sharing automation ids between accounts; typos in manually constructed ids.","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."],"exampleFix":"// before\nautomation = ConversationAdapters.get_automation(user, \"\")  # ValueError\n\n// after\nif is_none_or_empty(automation_id) or not automation_id.startswith(f\"automation_{user.uuid}_\"):\n    return None\nautomation = ConversationAdapters.get_automation(user, automation_id)","handlingStrategy":"validation","validationCode":"from khoj.utils import is_none_or_empty\nif is_none_or_empty(automation_id) or not automation_id.startswith(f\"automation_{user.uuid}_\"):\n    return None  # invalid or not owned\nautomation = ConversationAdapters.get_automation(user, automation_id)","typeGuard":"def is_valid_automation_id(user, automation_id: str | None) -> bool:\n    return bool(automation_id) and automation_id.startswith(f\"automation_{user.uuid}_\")","tryCatchPattern":"try:\n    automation = ConversationAdapters.get_automation(user, automation_id)\nexcept ValueError:\n    automation = None  # treat as invalid/not-found","preventionTips":["Validate id presence and ownership prefix at the API boundary.","Keep automation ids opaque to clients; look them up per user."],"tags":["khoj","automation","scheduler","authorization","validation"],"backgroundTag":"resource-ownership-validation","analyzedSha":"ae229ca894c0b80ad84664afcfdde523b5e87057","analyzedAt":"2026-08-27T03:32:41.843Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}