jamiepine/voicebox · error · HTTPException
Failed to delete model cache directory: {str(e)}
Error message
Failed to delete model cache directory: {str(e)} What it means
500 from DELETE /models/{model_name} when shutil.rmtree(repo_cache_dir) raises OSError. The route catches OSError specifically and forwards detail=f'Failed to delete model cache directory: {str(e)}'. Common OSError causes: permission denied, read-only mount, a file in the tree being open/locked by another process (model still memory-mapped by a running backend), or a path component vanishing mid-delete.
Source
Thrown at backend/routes/models.py:471
config = get_model_config(model_name)
if not config:
raise HTTPException(status_code=400, detail=f"Unknown model: {model_name}")
hf_repo_id = config.hf_repo_id
try:
unload_model_by_config(config)
cache_dir = hf_constants.HF_HUB_CACHE
repo_cache_dir = Path(cache_dir) / ("models--" + hf_repo_id.replace("/", "--"))
if not repo_cache_dir.exists():
raise HTTPException(status_code=404, detail=f"Model {model_name} not found in cache")
try:
shutil.rmtree(repo_cache_dir)
except OSError as e:
raise HTTPException(status_code=500, detail=f"Failed to delete model cache directory: {str(e)}")
return {"message": f"Model {model_name} deleted successfully"}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to delete model: {str(e)}")
View on GitHub (pinned to 51f49dea19)
Solutions
- Ensure the model is fully unloaded and no generate/speak/transcribe call is in flight — the route attempts unload but a concurrent load can race it.
- Run the backend with an account that has delete permission on HF_HUB_CACHE; on external drives check mount options (read-write, proper uid).
- On Windows, close any process that may have the files open (including file explorers previewing blobs) and retry.
- If the directory is partially deleted, manually rm -rf the remnants and re-download.
Example fix
# before — delete while model still loaded / mapped curl -X DELETE http://localhost:8000/models/qwen3-1.7b # OSError: text file busy # after — unload, wait, then delete curl -X POST http://localhost:8000/models/qwen3-1.7b/unload # wait for any in-flight /generate to finish, then: curl -X DELETE http://localhost:8000/models/qwen3-1.7b
Defensive patterns
Strategy: try-catch
Validate before calling
async function safeDelete(name: string) {
// ensure the model is unloaded and no generation is in flight first
await fetch(`/models/${encodeURIComponent(name)}/unload`, {method:'POST'}).catch(()=>{});
await waitForNoInflight(name);
return await fetch(`/models/${encodeURIComponent(name)}`, {method:'DELETE'});
} Try / catch
try {
await fetch(`/models/${name}`, {method:'DELETE'});
} catch (e) {
const d = e.response?.detail ?? '';
if (e.response?.status === 500 && /Failed to delete model cache directory/.test(d)) {
if (/busy|locked|permission|read-only/i.test(d)) {
// close holders / fix perms, then retry once
await new Promise(r => setTimeout(r, 1000));
await fetch(`/models/${name}`, {method:'DELETE'});
} else throw e;
} else throw e;
} Prevention
- Always unload the model and wait for in-flight generation to finish before deleting.
- Run the backend with delete permission on the HF cache; on Windows close processes holding the files.
- Avoid deleting from read-only or quirky filesystems (FAT/exFAT, locked network mounts).
When it happens
Trigger: Deleting a model whose weights are still memory-mapped by a loaded backend (the route does call unload_model_by_config first, but a concurrent generate can re-map files); deleting from a read-only or permission-restricted volume; antivirus/OS locking blob files on Windows; NFS/SMB stale file handles.
Common situations: Windows file locking when the model is still loaded; Linux process holding the safetensors mmap; destination on a FAT/exFAT external drive with permission quirks; user account lacks delete permission on the cache; concurrent /generate re-loads the model during delete.
Related errors
- Failed to delete model: {str(e)}
- {e}
- Current model cache directory not found
- Source and destination are the same directory
- Destination cannot be inside the current cache directory
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/581bea1938307d6e.
Report an issue: GitHub.