odysseus-dev/odysseus · error · HTTPException
Failed to delete event
Error message
Failed to delete event
What it means
Generic HTTP 500 from DELETE /events/{uid}. The handler loads the event, optionally records a CalDAV delete tombstone and appends an EXDATE for occurrence deletes, deletes the row, commits, and may queue a CalDAV delete push. Any non-HTTP exception — DB commit failure, malformed stored recurrence_exdates JSON, tombstone insert error — is rolled back, logged as 'Failed to delete event: <e>', and returned as this 500.
Source
Thrown at routes/calendar_routes.py:1357
if is_caldav:
ev.caldav_sync_pending = "update"
db.commit()
if is_caldav:
await _push_caldav_event_after_commit(owner, base_uid, "update")
return {"ok": True, "scope": "occurrence", "exdate": key}
if is_caldav:
_record_caldav_delete_tombstone(db, ev, owner)
db.delete(ev)
db.commit()
if is_caldav:
await _push_caldav_event_after_commit(owner, base_uid, "delete")
return {"ok": True}
except HTTPException:
raise
except Exception as e:
db.rollback()
logger.error("Failed to delete event: %s", e)
raise HTTPException(500, "Failed to delete event")
finally:
db.close()
@router.post("/calendars")
async def create_calendar(request: Request, name: str = "Imported", color: str = "#5b8abf"):
owner = _require_user(request)
_reserve_calendar_uploads(request, color)
db = SessionLocal()
try:
cal = CalendarCal(
id=str(uuid.uuid4()),
owner=owner,
name=name,
color=color,
source="local",
)
db.add(cal)
db.commit()View on GitHub (pinned to f9235ebbf1)
Solutions
- Check the server log ('Failed to delete event: <e>') for the underlying exception.
- If stored recurrence_exdates JSON is corrupt, repair or clear the value on that CalendarEvent row, then retry the delete.
- For 'database is locked', retry after concurrent writes finish or enable WAL.
- Guard the UI against double-submission of the delete button.
Defensive patterns
Strategy: try-catch
Validate before calling
// confirm the event still exists to get the clean 404 instead of a 500 race const ev = await api.get(`/events?start=...&end=...`); // or a single-event fetch if (!eventExists(ev, uid)) return; // already gone
Try / catch
try { await api.del(`/events/${uid}`, {params: {scope}}); }
catch (e) {
if (e.status === 404) return; // already deleted
if (e.status === 500) { // transient lock — one retry
await sleep(300);
return api.del(`/events/${uid}`, {params: {scope}});
}
throw e;
} Prevention
- Treat 404 on repeat deletes as success and 500 as 'check log, retry once'.
- Disable the delete control while the request is in flight to avoid racing duplicates.
- Keep recurrence_exdates data consistent — corrupt stored JSON makes occurrence deletes 500.
When it happens
Trigger: Database locked at commit while CalDAV sync runs concurrently; recurrence_exdates JSON corrupt so _recurrence_exdates throws during an occurrence delete; tombstone write violating a constraint; DB file/schema unavailable.
Common situations: Double-delete racing itself (two rapid clicks both past the 404 point); corrupt exdate data from an older import; schema drift after upgrade; SQLite contention with the background CalDAV push worker.
Related errors
- Failed to delete calendar
- Failed to list calendars
- Failed to list events
- Failed to create event
- Failed to update event
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/47010dcc09c2bc7f.
Report an issue: GitHub.