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:
            raise

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Read the logged exception ('Failed to create calendar: <e>') to identify the constraint or DB error.
  2. Truncate the calendar name to a sane length client-side before posting.
  3. If 'database is locked', retry after concurrent writes complete or enable WAL.
  4. 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

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


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/427135973718fefa. Report an issue: GitHub.