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.

Solutions

  1. Treat 404 on item removal as 'already gone' success when idempotency is desired.
  2. Confirm the item still appears in GET /stories/{story_id} before deleting.
  3. Guard against double-click on the remove button.
  4. 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

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


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

Appendix: 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)