jamiepine/voicebox · error · HTTPException
Profile not found
Error message
Profile not found
What it means
GET /profiles/{profile_id} calls profiles.get_profile; if it returns a falsy value (None) the route raises HTTP 404 'Profile not found'. This is the standard missing-resource guard: the id did not match any row in the profiles table. The lookup is by the string profile_id column, so a typo, a deleted row, or an id from another environment all collapse into this one response.
Source
Thrown at backend/routes/profiles.py:117
"voice_id": speaker_id,
"name": display_name,
"gender": gender,
"language": lang,
}
for speaker_id, display_name, gender, lang, _desc in QWEN_CUSTOM_VOICES
],
}
return {"engine": engine, "voices": []}
@router.get("/profiles/{profile_id}", response_model=models.VoiceProfileResponse)
async def get_profile(
profile_id: str,
db: Session = Depends(get_db),
):
"""Get a voice profile by ID."""
profile = await profiles.get_profile(profile_id, db)
if not profile:
raise HTTPException(status_code=404, detail="Profile not found")
return profile
@router.put("/profiles/{profile_id}", response_model=models.VoiceProfileResponse)
async def update_profile(
profile_id: str,
data: models.VoiceProfileCreate,
db: Session = Depends(get_db),
):
"""Update a voice profile."""
try:
profile = await profiles.update_profile(profile_id, data, db)
if not profile:
raise HTTPException(status_code=404, detail="Profile not found")
return profile
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
View on GitHub (pinned to 51f49dea19)
Solutions
- Verify the id against the current list returned by GET /profiles.
- On the client, treat a 404 here as 'evict this id from local cache and fall back to the list view'.
- Confirm you are sending the string profile_id returned at create time, not an internal numeric primary key.
- Trim whitespace from the path segment before sending.
Defensive patterns
Strategy: validation
Validate before calling
# Verify existence before the targeted GET
async def get_profile_or_evict(client, profile_id):
listing = (await client.get("/profiles")).json()
ids = {p["id"] for p in listing}
if profile_id not in ids:
return None # caller should evict the stale id
return await client.get(f"/profiles/{profile_id}") Try / catch
resp = await client.get(f"/profiles/{profile_id}")
if resp.status_code == 404:
evict_from_cache(profile_id)
show_default_view()
else:
resp.raise_for_status() Prevention
- Treat 404 here as authoritative and evict the id from all client caches.
- Always source profile ids from a fresh GET /profiles rather than bookmarks.
- Trim whitespace from ids before sending.
When it happens
Trigger: GET /profiles/{profile_id} with an id that was never created; an id of a profile deleted via DELETE /profiles/{id}; an id copy-pasted from a different deployment/database; a UUID with a stray leading/trailing space.
Common situations: Frontend cached a profile list, user deleted the profile in another tab, then the stale UI issues a GET; a bookmarked URL pointing at an old profile; passing the DB numeric PK instead of the string profile_id.
Related errors
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/7d1d2942a33ab596.
Report an issue: GitHub.