odysseus-dev/odysseus · error · HTTPException
Failed to create calendar
Error message
Failed to create calendar
What it means
Generic HTTP 500 from POST /calendars. The handler builds a CalendarCal row (uuid id, owner, name, color, source='local'), adds and commits it. Note this route has NO 'except HTTPException: raise' clause, but it also performs no _get_or_404 call, so in practice every failure is a genuine exception: DB error at commit, constraint violation, or an invalid color/name value rejected by the DB — logged as 'Failed to create calendar: <e>' and returned as this 500.
Source
Thrown at routes/calendar_routes.py:1380
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()
return {"ok": True, "id": cal.id, "name": cal.name, "color": cal.color}
except Exception as e:
db.rollback()
logger.error("Failed to create calendar: %s", e)
raise HTTPException(500, "Failed to create calendar")
finally:
db.close()
@router.put("/calendars/{cal_id}")
async def update_calendar(request: Request, cal_id: str, name: str = None, color: str = None):
owner = _require_user(request)
_reserve_calendar_uploads(request, color)
db = SessionLocal()
try:
cal = _get_or_404_calendar(db, cal_id, owner)
if name is not None:
cal.name = name
if color is not None:
cal.color = color
db.commit()
return {"ok": True}
except HTTPException:
raiseView on GitHub (pinned to f9235ebbf1)
Solutions
- Read the logged exception ('Failed to create calendar: <e>') to identify the constraint or DB error.
- Truncate the calendar name to a sane length client-side before posting.
- If 'database is locked', retry after concurrent writes complete or enable WAL.
- Apply pending schema migrations if a column mismatch is reported.
Defensive patterns
Strategy: try-catch
Validate before calling
const name = String(rawName).trim().slice(0, 100) || 'Imported';
const color = /^#[0-9a-fA-F]{6}$/.test(rawColor) ? rawColor : '#5b8abf';
await api.post('/calendars', null, {params: {name, color}}); Try / catch
try { await api.post('/calendars', null, {params: {name, color}}); }
catch (e) {
if (e.status === 500) { /* server log 'Failed to create calendar' has root cause */ throw e; }
throw e;
} Prevention
- Cap the calendar name length client-side before posting.
- Send color as a #rrggbb string from the picker.
- Retry once on 500 if the app uses SQLite — lock contention with sync workers is the usual cause.
When it happens
Trigger: Database locked or unavailable at commit; name/color exceeding column limits (very long names); NOT NULL/unique constraint on id colliding only in pathological cases; disk full.
Common situations: Creating a calendar while the CalDAV sync worker holds the SQLite write lock; schema not migrated so CalendarCal lacks expected columns; user pasting an extremely long calendar name from clipboard.
Related errors
- Failed to delete calendar
- Failed to list calendars
- Failed to update calendar
- Failed to create document: {e}
- Failed to fetch document library: {e}
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/427135973718fefa.
Report an issue: GitHub.