jamiepine/voicebox · warning · HTTPException

Cannot delete CUDA backend while it is active. Switch to CPU

Error message

Cannot delete CUDA backend while it is active. Switch to CPU first.

What it means

HTTP 409 raised by DELETE /backend/cuda when cuda.is_cuda_active() returns true, i.e. the current process is itself the CUDA binary (env var VOICEBOX_BACKEND_VARIANT == 'cuda'). Deleting the onedir bundle out from under a running CUDA process would corrupt the active backend, so the endpoint refuses and instructs you to switch to CPU first.

Source

Thrown at backend/routes/cuda.py:57

        raise HTTPException(status_code=409, detail="CUDA backend download already in progress")

    async def _download():
        try:
            await cuda.download_cuda_binary()
        except Exception as e:
            logger.error("CUDA download failed: %s", e)

    create_background_task(_download())
    return {"message": "CUDA backend download started", "progress_key": "cuda-backend"}


@router.delete("/backend/cuda")
async def delete_cuda_backend():
    """Delete the downloaded CUDA backend binary."""
    from ..services import cuda

    if cuda.is_cuda_active():
        raise HTTPException(
            status_code=409,
            detail="Cannot delete CUDA backend while it is active. Switch to CPU first.",
        )

    deleted = await cuda.delete_cuda_binary()
    if not deleted:
        raise HTTPException(status_code=404, detail="No CUDA backend found to delete")

    return {"message": "CUDA backend deleted"}


@router.get("/backend/cuda-progress")
async def get_cuda_download_progress():
    """Get CUDA backend download progress via Server-Sent Events."""
    progress_manager = get_progress_manager()

    async def event_generator():
        async for event in progress_manager.subscribe("cuda-backend"):

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Restart the server on the CPU backend (unset/switch VOICEBOX_BACKEND_VARIANT), then issue DELETE /backend/cuda.
  2. For upgrades, prefer letting startup auto-update handle it rather than manual delete while active.
  3. Check GET /backend/cuda status.active before offering the delete action.

Example fix

// before
await fetch('/backend/cuda', { method: 'DELETE' });
// after
const status = await fetch('/backend/cuda').then(r => r.json());
if (status.active) { alert('Switch to the CPU backend before deleting CUDA'); return; }
await fetch('/backend/cuda', { method: 'DELETE' });
Defensive patterns

Strategy: validation

Validate before calling

const status = await fetch('/backend/cuda').then(r => r.json());
if (status.active) throw new Error('switch to CPU backend before deleting');

Type guard

function isCudaActive(s): s is { active: true } { return s?.active === true; }

Try / catch

const r = await fetch('/backend/cuda', { method:'DELETE' });
if (r.status === 409) { const { detail } = await r.json(); /* instructs CPU switch */ }

Prevention

When it happens

Trigger: Calling DELETE /backend/cuda while the server is running as the CUDA variant (the process was launched from the downloaded CUDA executable).

Common situations: Trying to free disk or force an update without first restarting on CPU; an update script running inside the CUDA backend process.

Related errors


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