{"record":{"id":"cd576d63b4c7c976","repo":"odysseus-dev/odysseus","slug":"failed-to-create-event","errorCode":null,"errorMessage":"Failed to create event","messagePattern":"Failed to create event","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"routes/calendar_routes.py","lineNumber":1263,"sourceCode":"                dtstart=dtstart,\n                dtend=dtend,\n                all_day=data.all_day,\n                is_utc=_is_utc and not data.all_day,\n                rrule=data.rrule or \"\",\n                color=data.color or None,\n                caldav_sync_pending=\"create\" if cal.source == \"caldav\" else None,\n            )\n            db.add(ev)\n            db.commit()\n            if cal.source == \"caldav\":\n                await _push_caldav_event_after_commit(owner, uid, \"create\")\n            return {\"ok\": True, \"uid\": uid}\n        except HTTPException:\n            raise\n        except Exception as e:\n            db.rollback()\n            logger.error(\"Failed to create event: %s\", e)\n            raise HTTPException(500, \"Failed to create event\")\n        finally:\n            db.close()\n\n    @router.put(\"/events/{uid}\")\n    async def update_event(request: Request, uid: str, data: EventUpdate):\n        owner = _require_user(request)\n        _reserve_calendar_uploads(request, data.color, data.description, data.location)\n        try:\n            base_uid = _resolve_base_uid(uid)\n        except ValueError as e:\n            raise HTTPException(400, str(e))\n        db = SessionLocal()\n        try:\n            ev = _get_or_404_event(db, base_uid, owner)\n            if data.summary is not None:\n                ev.summary = data.summary\n            if data.description is not None:\n                ev.description = data.description","sourceCodeStart":1245,"sourceCodeEnd":1281,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/calendar_routes.py#L1245-L1281","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nbody: JSON.stringify({summary: 'Lunch', dtstart: '05/13/2026 1:00 PM'})\n\n// after\nbody: JSON.stringify({summary: 'Lunch', dtstart: '2026-05-13T13:00:00', dtend: '2026-05-13T14:00:00'})","handlingStrategy":"validation","validationCode":"function toIsoOrNull(v) {\n  const d = new Date(v);\n  return isNaN(d.getTime()) ? null : d.toISOString();\n}\nconst dtstart = toIsoOrNull(payload.dtstart);\nif (!dtstart) throw new Error('dtstart must be a valid date');\nawait api.post('/events', {...payload, dtstart, dtend: toIsoOrNull(payload.dtend) ?? undefined});","typeGuard":null,"tryCatchPattern":"try { await api.post('/events', payload); }\ncatch (e) {\n  if (e.status === 500) { /* check server log 'Failed to create event' for the field */ throw e; }\n  throw e;\n}","preventionTips":["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."],"tags":["http-500","fastapi","database","datetime"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}