jamiepine/voicebox · warning · HTTPException
Story item not found
Error message
Story item not found
What it means
Returned by DELETE /stories/{story_id}/items/{item_id} when stories.remove_item_from_story returns falsy (HTTP 404). Either the story or the item (or their combination) was not found, so nothing was removed.
Source
Thrown at backend/routes/stories.py:94
db: Session = Depends(get_db),
):
"""Add a generation to a story."""
item = await stories.add_item_to_story(story_id, data, db)
if not item:
raise HTTPException(status_code=404, detail="Story or generation not found")
return item
@router.delete("/stories/{story_id}/items/{item_id}")
async def remove_story_item(
story_id: str,
item_id: str,
db: Session = Depends(get_db),
):
"""Remove a story item from a story."""
success = await stories.remove_item_from_story(story_id, item_id, db)
if not success:
raise HTTPException(status_code=404, detail="Story item not found")
return {"message": "Item removed successfully"}
@router.put("/stories/{story_id}/items/times")
async def update_story_item_times(
story_id: str,
data: models.StoryItemBatchUpdate,
db: Session = Depends(get_db),
):
"""Update story item timecodes."""
success = await stories.update_story_item_times(story_id, data, db)
if not success:
raise HTTPException(status_code=400, detail="Invalid timecode update request")
return {"message": "Item timecodes updated successfully"}
@router.put("/stories/{story_id}/items/reorder", response_model=list[models.StoryItemDetail])
async def reorder_story_items(View on GitHub (pinned to 51f49dea19)
Solutions
- Treat 404 on item removal as 'already gone' success when idempotency is desired.
- Confirm the item still appears in GET /stories/{story_id} before deleting.
- Guard against double-click on the remove button.
- Re-fetch the story detail to reconcile item ids.
Example fix
// before
await api.delete(`/stories/${sid}/items/${iid}`);
// after
try { await api.delete(`/stories/${sid}/items/${iid}`); }
catch (e) { if (e.status !== 404) throw e; } Defensive patterns
Strategy: fallback
Validate before calling
async function itemInStory(sid, iid) {
const s = await (await fetch(`/api/stories/${encodeURIComponent(sid)}`)).json();
return Array.isArray(s.items) && s.items.some(i => i.id === iid);
} Type guard
function isItemId(v) { return typeof v === 'string' && v.trim().length >= 8; } Try / catch
try { await api.delete(`/stories/${sid}/items/${iid}`); }
catch (e) { if (e.response?.status === 404) return; throw e; } Prevention
- Treat 404 on item removal as 'already gone'.
- Guard against double-click on the remove button.
- Re-fetch story detail to reconcile item ids.
When it happens
Trigger: Removing an item that was already removed, an item_id that does not exist under the given story, or a story_id that does not exist. The composite key (story_id, item_id) does not match a row.
Common situations: Double-remove after optimistic UI update. item_id from a different story. Story deleted while its items list was open.
Related errors
- Story item not found or invalid trim values
- Story not found
- Story or generation not found
- No ROCm backend found to delete
- Voice profile '{data.profile}' not found.
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/18e4ab97a20dd349.
Report an issue: GitHub.