jamiepine/voicebox · error · HTTPException
Channel not found
Error message
Channel not found
What it means
HTTP 404 raised by GET /channels/{channel_id} when no AudioChannel row matches the supplied ID. The route delegates to channels.get_channel(), which queries the database by primary key and returns None on a miss; the handler then converts that None into a 404 'Channel not found'. It is a pure lookup miss, not a permission or format error.
Source
Thrown at backend/routes/channels.py:39
data: models.AudioChannelCreate,
db: Session = Depends(get_db),
):
"""Create a new audio channel."""
try:
return await channels.create_channel(data, db)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
@router.get("/channels/{channel_id}", response_model=models.AudioChannelResponse)
async def get_channel(
channel_id: str,
db: Session = Depends(get_db),
):
"""Get an audio channel by ID."""
channel = await channels.get_channel(channel_id, db)
if not channel:
raise HTTPException(status_code=404, detail="Channel not found")
return channel
@router.put("/channels/{channel_id}", response_model=models.AudioChannelResponse)
async def update_channel(
channel_id: str,
data: models.AudioChannelUpdate,
db: Session = Depends(get_db),
):
"""Update an audio channel."""
try:
channel = await channels.update_channel(channel_id, data, db)
if not channel:
raise HTTPException(status_code=404, detail="Channel not found")
return channel
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
View on GitHub (pinned to 51f49dea19)
Solutions
- Call GET /channels to list all valid channel IDs and copy the exact UUID.
- Confirm the ID you hold came from a create/list response and was refreshed after any delete.
- Strip whitespace and validate the ID is a 36-char UUID before sending.
- Treat a 404 on this endpoint as 'resource gone' and clear it from the client cache.
Example fix
// before
const r = await fetch(`/channels/${someDeviceId}`);
// after
const list = await fetch('/channels').then(r => r.json());
const ch = list.find(c => c.id === expectedId);
if (!ch) throw new Error('channel does not exist');
const r = await fetch(`/channels/${ch.id}`); Defensive patterns
Strategy: validation
Validate before calling
const channels = await fetch('/channels').then(r => r.json());
const exists = channels.some(c => c.id === channelId);
if (!exists) throw new Error(`channel ${channelId} not found`); Type guard
function isChannelList(v): v is Array<{ id: string; name: string }> {
return Array.isArray(v) && v.every(c => typeof c?.id === 'string');
} Try / catch
const r = await fetch(`/channels/${channelId}`);
if (r.status === 404) { /* clear stale id, refresh list */ } Prevention
- Always source channel IDs from a fresh GET /channels response.
- Clear cached IDs after observing a delete.
- Strip whitespace and validate UUID format before sending.
When it happens
Trigger: Calling GET /channels/{channel_id} with a UUID that was never created, has been deleted, is malformed, or belongs to a different resource type (e.g. a device_id or profile_id).
Common situations: Frontend holds a stale channel_id in memory after the channel was deleted in another tab; copy-paste truncation of the UUID; trailing whitespace or surrounding quotes accidentally sent; test calling a randomly generated UUID without first creating the channel.
Related errors
- {exception message from set_channel_voices (ValueError)}
- {exception message from update_channel (ValueError)}
- {exception message from delete_channel (ValueError)}
- {exception message from get_channel_voices (ValueError)}
- No CUDA backend found to delete
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/f9884e308dc7e281.
Report an issue: GitHub.