{"record":{"id":"fe1e1950b033ebb1","repo":"jamiepine/voicebox","slug":"failed-to-clear-cache-str-e","errorCode":null,"errorMessage":"Failed to clear cache: {str(e)}","messagePattern":"Failed to clear cache: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"backend/routes/tasks.py","lineNumber":42,"sourceCode":"    with progress_manager._lock:\n        progress_manager._progress.clear()\n        progress_manager._last_notify_time.clear()\n        progress_manager._last_notify_progress.clear()\n\n    return {\"message\": \"All task state cleared\"}\n\n\n@router.post(\"/cache/clear\")\nasync def clear_cache():\n    \"\"\"Clear all voice prompt caches (memory and disk).\"\"\"\n    try:\n        deleted_count = clear_voice_prompt_cache()\n        return {\n            \"message\": \"Voice prompt cache cleared successfully\",\n            \"files_deleted\": deleted_count,\n        }\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=f\"Failed to clear cache: {str(e)}\")\n\n\n@router.get(\"/tasks/active\", response_model=models.ActiveTasksResponse)\nasync def get_active_tasks():\n    \"\"\"Return all currently active downloads and generations.\"\"\"\n    task_manager = get_task_manager()\n    progress_manager = get_progress_manager()\n\n    active_downloads = []\n    task_manager_downloads = task_manager.get_active_downloads()\n    progress_active = progress_manager.get_all_active()\n\n    download_map = {task.model_name: task for task in task_manager_downloads}\n    progress_map = {p[\"model_name\"]: p for p in progress_active}\n\n    all_model_names = set(download_map.keys()) | set(progress_map.keys())\n    for model_name in all_model_names:\n        task = download_map.get(model_name)","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/backend/routes/tasks.py#L24-L60","documentation":"Raised (HTTP 500) by POST /cache/clear when clear_voice_prompt_cache() throws. That function clears an in-memory dict and unlinks *.prompt and combined_*.wav files under the configured cache dir, already swallowing per-file unlink errors as warnings — so a propagated exception almost always comes from _get_cache_dir()/config.get_cache_dir() (e.g. misconfigured path), a torch import/init failure, or an OS error creating/reading the directory itself, not from individual file deletes.","triggerScenarios":"The cache directory path is unset/misconfigured in config, the process lacks permission to stat the directory, the filesystem is read-only, or the torch dependency failed to initialize so the module-level _memory_cache or torch.save machinery errors.","commonSituations":"Container runs with a read-only mount for the cache dir, wrong CACHE_DIR env var pointing at a non-writable path, or running as a user without delete permission on the cached files' parent.","solutions":["Confirm the configured cache dir exists and is writable/deletable by the server process.","Check the server log — the wrapped exception names the exact path/permission problem.","Because per-file deletes are already best-effort, a 500 here usually points to config/permissions, not data — fix the env, not the cache contents.","If torch failed to import, validate the Python environment (requirements.txt / image) before retrying."],"exampleFix":"# before\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=f\"Failed to clear cache: {str(e)}\")\n\n# after (avoid leaking path/error internals; log full detail server-side)\n    except OSError as e:\n        logger.warning(\"cache clear hit OS error: %s\", e)\n        return {\"message\": \"Cache cleared with warnings\", \"files_deleted\": 0}\n    except Exception:\n        logger.exception(\"clear_voice_prompt_cache failed\")\n        raise HTTPException(status_code=500, detail=\"Failed to clear cache\")","handlingStrategy":"try-catch","validationCode":"// Pre-flight: confirm the cache dir is writable before clearing.\nasync function canClearCache(api) {\n  const health = await api.getHealth().catch(() => null);\n  return Boolean(health && health.cache_dir_writable !== false);\n}","typeGuard":"function isRetryableCacheError(e) {\n  return e?.status === 500 && /cache/i.test(String(e.detail ?? ''));\n}","tryCatchPattern":"try { await api.clearCache(); notify('Cache cleared'); }\ncatch (e) {\n  if (e.status === 500) notify('Could not clear cache — check server permissions/config');\n  else throw e;\n}","preventionTips":["Mount the cache directory as writable/deletable by the server process.","Validate CACHE_DIR / storage config at startup, not only when clearing.","Treat this 500 as an ops/config issue — per-file deletes are already best-effort inside the function."],"tags":["api","cache","error-handling","filesystem","permissions","information-disclosure"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}