jamiepine/voicebox · error · HTTPException
Preset not found
Error message
Preset not found
What it means
HTTP 404 raised by GET /effects/presets/{preset_id} when effects_mod.get_preset() returns None, i.e. no EffectPreset row matches the preset_id (built-in or user). The handler raises 404 'Preset not found'. This is a pure lookup miss on the presets table.
Source
Thrown at backend/routes/effects.py:89
return models.AvailableEffectsResponse(effects=[models.AvailableEffect(**e) for e in _get_effects()])
@router.get("/effects/presets", response_model=list[models.EffectPresetResponse])
async def list_effect_presets(db: Session = Depends(get_db)):
"""List all effect presets (built-in + user-created)."""
from ..services import effects as effects_mod
return effects_mod.list_presets(db)
@router.get("/effects/presets/{preset_id}", response_model=models.EffectPresetResponse)
async def get_effect_preset(preset_id: str, db: Session = Depends(get_db)):
"""Get a specific effect preset."""
from ..services import effects as effects_mod
preset = effects_mod.get_preset(preset_id, db)
if not preset:
raise HTTPException(status_code=404, detail="Preset not found")
return preset
@router.post("/effects/presets", response_model=models.EffectPresetResponse)
async def create_effect_preset(
data: models.EffectPresetCreate,
db: Session = Depends(get_db),
):
"""Create a new effect preset."""
from ..services import effects as effects_mod
try:
return effects_mod.create_preset(data, db)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
@router.put("/effects/presets/{preset_id}", response_model=models.EffectPresetResponse)View on GitHub (pinned to 51f49dea19)
Solutions
- GET /effects/presets to list valid preset IDs before referencing one.
- On 404, refresh the presets list and fall back to a default/built-in preset.
- Do not cache preset_ids long-term; they can be deleted by the user.
Example fix
// before
const p = await fetch(`/effects/presets/${id}`).then(r => r.json());
// after
const r = await fetch(`/effects/presets/${id}`);
if (r.status === 404) { const all = await fetch('/effects/presets').then(r => r.json()); return all[0]; }
return r.json(); Defensive patterns
Strategy: validation
Validate before calling
const presets = await fetch('/effects/presets').then(r => r.json());
if (!presets.some(p => p.id === presetId)) throw new Error('preset missing'); Type guard
function isPresetList(v): v is Array<{ id: string }> { return Array.isArray(v) && v.every(p => typeof p?.id === 'string'); } Try / catch
const r = await fetch(`/effects/presets/${id}`);
if (r.status === 404) { const all = await fetch('/effects/presets').then(r => r.json()); return all[0]; } Prevention
- Source preset IDs from a fresh presets list.
- Fall back to a built-in preset on 404.
- Do not cache preset IDs long-term.
When it happens
Trigger: GET /effects/presets/{preset_id} with an ID that was never created, was deleted, or is malformed.
Common situations: Referencing a user preset that was deleted; storing a preset_id across sessions without refreshing; typo or copy-paste error in the ID.
Related errors
- Generation not found
- Source audio file not found
- Channel not found
- {exception message from set_channel_voices (ValueError)}
- No CUDA backend found to delete
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/cd6c973f635438dc.
Report an issue: GitHub.