jamiepine/voicebox · error · HTTPException

Generation not found

Error message

Generation not found

What it means

Returned as HTTP 404 by POST /generate/{generation_id}/retry. The route queries DBGeneration by id and raises this 404 when first() returns None. Retry only operates on an existing generation row that previously failed; without the row there is nothing to retry.

Source

Thrown at backend/routes/generations.py:153

            seed=data.seed,
            normalize=data.normalize,
            effects_chain=effects_chain_config,
            instruct=data.instruct,
            mode="generate",
            max_chunk_chars=data.max_chunk_chars,
            crossfade_ms=data.crossfade_ms,
        )
    )

    return generation


@router.post("/generate/{generation_id}/retry", response_model=models.GenerationResponse)
async def retry_generation(generation_id: str, db: Session = Depends(get_db)):
    """Retry a failed generation using the same parameters."""
    gen = db.query(DBGeneration).filter_by(id=generation_id).first()
    if not gen:
        raise HTTPException(status_code=404, detail="Generation not found")

    if (gen.status or "completed") != "failed":
        raise HTTPException(status_code=400, detail="Only failed generations can be retried")

    gen.status = "generating"
    gen.error = None
    gen.audio_path = ""
    gen.duration = 0
    db.commit()
    db.refresh(gen)

    task_manager = get_task_manager()
    task_manager.start_generation(
        task_id=generation_id,
        profile_id=gen.profile_id,
        text=gen.text,
    )

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Confirm the generation still exists via GET /history (with a failed-status filter) before offering retry.
  2. On 404, remove the entry from the UI and stop offering retry.
  3. Re-source the id from a fresh history listing rather than a cached value.
  4. If the row is expected, check whether a cleanup job or another session deleted it.

Example fix

// before
await api.post(`/generate/${failedId}/retry`);
// after
const failed = await api.get('/history', { params: { status: 'failed' } });
if (!failed.items.some(g => g.id === failedId)) { removeCard(failedId); return; }
await api.post(`/generate/${failedId}/retry`);
Defensive patterns

Strategy: validation

Validate before calling

gen = db.query(DBGeneration).filter_by(id=generation_id).first()
if gen is None:
    raise GenerationMissing(generation_id)  # would 404
# safe to POST /generate/{id}/retry

Type guard

def generation_failed_and_exists(gen) -> bool:
    return gen is not None and (gen.status or 'completed') == 'failed'

Try / catch

try:
    client.post(f'/generate/{generation_id}/retry')
except HTTPStatusError as e:
    if e.response.status_code == 404:
        remove_card(generation_id)  # swept by clear-failed or deleted elsewhere
        return
    raise

Prevention

When it happens

Trigger: POST /generate/{id}/retry with an id not in the Generation table; retrying a generation that was deleted (e.g. by 'clear failed'); passing a profile_id or version_id where a generation_id is expected.

Common situations: User clicks retry on a failed generation that was swept by 'clear failed'; stale UI after a history cleanup; id copied from a different environment; generation row never persisted because the initial create failed.

Related errors


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