jamiepine/voicebox · warning · HTTPException
Cannot delete ROCm backend while it is active. Switch to CPU
Error message
Cannot delete ROCm backend while it is active. Switch to CPU first.
What it means
Returned by DELETE /backend/rocm when rocm.is_rocm_active() returns true (HTTP 409). The handler refuses to delete the binary while it is the active backend, to avoid removing code that is currently serving inference. The message instructs switching to CPU first.
Source
Thrown at backend/routes/rocm.py:50
raise HTTPException(status_code=409, detail="ROCm backend download already in progress")
async def _download():
try:
await rocm.download_rocm_binary()
except Exception as e:
logger.error("ROCm download failed: %s", e)
create_background_task(_download())
return {"message": "ROCm backend download started", "progress_key": rocm.PROGRESS_KEY}
@router.delete("/backend/rocm")
async def delete_rocm_backend():
"""Delete the downloaded ROCm backend binary."""
from ..services import rocm
if rocm.is_rocm_active():
raise HTTPException(
status_code=409,
detail="Cannot delete ROCm backend while it is active. Switch to CPU first.",
)
deleted = await rocm.delete_rocm_binary()
if not deleted:
raise HTTPException(status_code=404, detail="No ROCm backend found to delete")
return {"message": "ROCm backend deleted"}
@router.get("/backend/rocm-progress")
async def get_rocm_download_progress():
"""Get ROCm backend download progress via Server-Sent Events."""
progress_manager = get_progress_manager()
async def event_generator():
async for event in progress_manager.subscribe("rocm-backend"):View on GitHub (pinned to 51f49dea19)
Solutions
- Switch the active backend to CPU via the backend settings endpoint, confirm is_rocm_active() is false, then call DELETE /backend/rocm.
- Verify the switch completed before retrying the delete.
- In automation, check the active-backend endpoint first and skip/switch as needed.
- Do not retry the delete on a 409 loop — it will keep failing until the switch takes effect.
Example fix
# before
await client.delete('/backend/rocm')
# after
await client.post('/backend/switch', json={'backend': 'cpu'})
await wait_until(lambda: not await is_rocm_active())
await client.delete('/backend/rocm') Defensive patterns
Strategy: validation
Validate before calling
async function rocmActive() {
const s = await (await fetch('/api/backend/rocm-status')).json();
return s.active === true;
} Type guard
function isRocmActive(s) { return !!s && s.active === true; } Try / catch
try { await api.delete('/backend/rocm'); }
catch (e) {
if (e.response?.status === 409) { await switchToCpu(); await retryDelete(); return; }
throw e;
} Prevention
- Switch the active backend to CPU before deleting ROCm.
- Verify is_rocm_active() is false before retrying the delete.
- In automation, branch on active state instead of looping on 409.
When it happens
Trigger: Issuing DELETE /backend/rocm while the backend is configured to use ROCm (is_rocm_active() true). Attempting cleanup without first flipping the active backend setting to CPU.
Common situations: User uninstalls ROCm hardware/driver and wants to reclaim disk but forgot to switch the backend selector. Automation script that deletes backends without checking active state.
Related errors
- ROCm backend download already in progress
- No ROCm backend found to delete
- {exception message from update_channel (ValueError)}
- {exception message from delete_channel (ValueError)}
- CUDA backend already downloaded
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/18ff70cba6fc732d.
Report an issue: GitHub.