{"record":{"id":"0536af796cc5e096","repo":"odysseus-dev/odysseus","slug":"this-task-has-no-clearable-cache","errorCode":null,"errorMessage":"This task has no clearable cache","messagePattern":"This task has no clearable cache","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"routes/task_routes.py","lineNumber":597,"sourceCode":"            if not task:\n                raise HTTPException(404, \"Task not found\")\n            if user and task.owner != user:\n                raise HTTPException(403, \"Access denied\")\n            action = task.action or \"\"\n        finally:\n            db.close()\n\n        cache_tables = {\n            \"summarize_emails\": (\"email_summaries\",),\n            \"draft_email_replies\": (\"email_ai_replies\",),\n            \"email_auto_translate\": (\"email_translations\",),\n            \"extract_email_events\": (\"email_calendar_extractions\",),\n            \"learn_sender_signatures\": (\"sender_signatures\",),\n            \"check_email_urgency\": (\"email_tags\", \"email_urgency_alerts\"),\n        }\n        tables = cache_tables.get(action)\n        if not tables:\n            raise HTTPException(400, \"This task has no clearable cache\")\n\n        import sqlite3\n        from pathlib import Path\n        from routes.email_helpers import SCHEDULED_DB, OWNER_SCOPED_EMAIL_CACHE_TABLES, _email_cache_owner_clause\n\n        cleared = {}\n        conn = sqlite3.connect(SCHEDULED_DB)\n        try:\n            for table in tables:\n                try:\n                    if table == \"email_tags\" and user:\n                        before = conn.execute(\n                            \"SELECT COUNT(*) FROM email_tags WHERE owner = ? OR owner = ''\",\n                            (user,),\n                        ).fetchone()[0]\n                        conn.execute(\"DELETE FROM email_tags WHERE owner = ? OR owner = ''\", (user,))\n                    elif table in OWNER_SCOPED_EMAIL_CACHE_TABLES and user:\n                        owner_clause, owner_params = _email_cache_owner_clause(user)","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/task_routes.py#L579-L615","documentation":"POST /api/tasks/{task_id}/clear-cache maps the task's action to clearable cache tables via a whitelist (summarize_emails, draft_email_replies, email_auto_translate, extract_email_events, learn_sender_signatures, check_email_urgency). If the task's action is not in that dict (including non-action tasks whose action field is empty), there is nothing derived to purge and the route returns HTTP 400.","triggerScenarios":"Calling clear-cache on an llm/research task (action empty), an action task with an action name outside the whitelist (e.g. action_run_local), or a custom/new action whose cache table was never registered in cache_tables.","commonSituations":"UI shows a 'Clear cache' button on every task row instead of only cached email actions; new built-in action added without extending cache_tables; user assumes all tasks have server-side caches.","solutions":["Only offer/attempt clear-cache for tasks whose action is one of the whitelisted email actions.","Check task.action client-side against the whitelist before calling the endpoint.","When adding a new derived-cache action server-side, register its tables in the cache_tables dict so the endpoint supports it."],"exampleFix":"// before\nrows.forEach(t => t.showClearCache = true);\n\n// after\nconst CLEARABLE = new Set(['summarize_emails','draft_email_replies','email_auto_translate','extract_email_events','learn_sender_signatures','check_email_urgency']);\nrows.forEach(t => t.showClearCache = CLEARABLE.has(t.action));","handlingStrategy":"type-guard","validationCode":"const CLEARABLE_ACTIONS = new Set(['summarize_emails','draft_email_replies','email_auto_translate','extract_email_events','learn_sender_signatures','check_email_urgency']);\nconst canClear = (task) => CLEARABLE_ACTIONS.has(task.action ?? '');","typeGuard":"function hasClearableCache(task: {action?: string | null}): boolean {\n  const CLEARABLE = new Set(['summarize_emails','draft_email_replies','email_auto_translate','extract_email_events','learn_sender_signatures','check_email_urgency']);\n  return typeof task.action === 'string' && CLEARABLE.has(task.action);\n}","tryCatchPattern":null,"preventionTips":["Gate the Clear-cache button on the whitelist above (keep it in sync when the server adds actions).","Consider exposing cache_tables from the server so the client never hardcodes it."],"tags":["tasks","cache","http-400","validation","whitelist"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}