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

  1. Switch the active backend to CPU via the backend settings endpoint, confirm is_rocm_active() is false, then call DELETE /backend/rocm.
  2. Verify the switch completed before retrying the delete.
  3. In automation, check the active-backend endpoint first and skip/switch as needed.
  4. 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

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


AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12). Data as JSON: /api/errors/18ff70cba6fc732d. Report an issue: GitHub.