odysseus-dev/odysseus · error · HTTPException
Failed to create event
Error message
Failed to create event
What it means
Generic HTTP 500 from POST /events. The handler resolves the calendar, parses dtstart/dtend with timezone detection, builds a CalendarEvent row, commits, and optionally queues a CalDAV push. Any non-HTTP exception in that path — unparseable datetime despite the tz-detecting parser, DB failure at commit, constraint violation — is rolled back, logged as 'Failed to create event: <e>', and surfaced as this 500.
Source
Thrown at routes/calendar_routes.py:1263
dtstart=dtstart,
dtend=dtend,
all_day=data.all_day,
is_utc=_is_utc and not data.all_day,
rrule=data.rrule or "",
color=data.color or None,
caldav_sync_pending="create" if cal.source == "caldav" else None,
)
db.add(ev)
db.commit()
if cal.source == "caldav":
await _push_caldav_event_after_commit(owner, uid, "create")
return {"ok": True, "uid": uid}
except HTTPException:
raise
except Exception as e:
db.rollback()
logger.error("Failed to create event: %s", e)
raise HTTPException(500, "Failed to create event")
finally:
db.close()
@router.put("/events/{uid}")
async def update_event(request: Request, uid: str, data: EventUpdate):
owner = _require_user(request)
_reserve_calendar_uploads(request, data.color, data.description, data.location)
try:
base_uid = _resolve_base_uid(uid)
except ValueError as e:
raise HTTPException(400, str(e))
db = SessionLocal()
try:
ev = _get_or_404_event(db, base_uid, owner)
if data.summary is not None:
ev.summary = data.summary
if data.description is not None:
ev.description = data.descriptionView on GitHub (pinned to f9235ebbf1)
Solutions
- Check the server log ('Failed to create event: <e>') for the underlying exception.
- Send dtstart/dtend as ISO 8601 ('2026-05-13T10:00:00' or with offset/Z).
- If the log shows a constraint or missing column, run schema migrations.
- If 'database is locked', retry once after concurrent writes settle or move off contended SQLite.
Example fix
// before
body: JSON.stringify({summary: 'Lunch', dtstart: '05/13/2026 1:00 PM'})
// after
body: JSON.stringify({summary: 'Lunch', dtstart: '2026-05-13T13:00:00', dtend: '2026-05-13T14:00:00'}) Defensive patterns
Strategy: validation
Validate before calling
function toIsoOrNull(v) {
const d = new Date(v);
return isNaN(d.getTime()) ? null : d.toISOString();
}
const dtstart = toIsoOrNull(payload.dtstart);
if (!dtstart) throw new Error('dtstart must be a valid date');
await api.post('/events', {...payload, dtstart, dtend: toIsoOrNull(payload.dtend) ?? undefined}); Try / catch
try { await api.post('/events', payload); }
catch (e) {
if (e.status === 500) { /* check server log 'Failed to create event' for the field */ throw e; }
throw e;
} Prevention
- Always serialize datetimes to ISO 8601 (with offset or Z) before posting.
- Validate dtend > dtstart client-side when both are present.
- On 500, consult the server log before retrying — blind retries of a malformed payload always fail.
When it happens
Trigger: dtstart/dtstart format the parser cannot handle at all (e.g. '13/45/2026', empty string after EventCreate validation); dtend earlier-format mismatch causing a comparison error; database locked at commit; NOT NULL constraint hit for a field the client omitted; failure scheduling the CalDAV push.
Common situations: Client sending locale-formatted dates (MM/DD/YYYY) instead of ISO 8601; SQLite write contention with the sync worker; schema drift after upgrading without migrating; all-day event posted with dtend but no dtstart semantics the model expects.
Related errors
- Failed to update event
- Failed to delete calendar
- Failed to list calendars
- Failed to list events
- Failed to delete event
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/cd576d63b4c7c976.
Report an issue: GitHub.