Repository navigation
Description
Problem Description
Events created or updated via the Huly interface are not synced to the connected Google Calendar (outbound sync fails).
While inbound events (from Google to Huly) sync correctly, outbound events fail to sync without producing any error logs in the server or UI. This silent failure makes it extremely difficult to identify the underlying cause of the synchronization issue (e.g., API rejection, payload formatting errors, timezone mismatch, etc.).
Environment
- Version: v0.7.353 (hardcoreeng/* images)
- Deployment: Dokploy (docker-compose)
Root Cause Analysis
The core issue stems from missing error handling and unhandled promise rejections in the asynchronous operations of the pod-calendar service:
-
Unhandled Promise in
main.ts(Webhook Handler):
The/event(POST) webhook triggersOutcomingClient.pushasynchronously but does not wait for or handle the result correctly. If an exception occurs within thepushmethod, it gets lost because there is nocatchblock on the promise chain.// services/calendar/pod-calendar/src/main.ts handler: async (req, res) => { // ... // The error is completely swallowed here. void OutcomingClient.push(ctx, accountClient, workspace, event, type) res.send() // Returns success prematurely }
-
Missing
try/catchon Google API Calls:
Within theOutcomingClientclass, specifically in thecreatemethod, the call tothis.calendar.events.insertis not wrapped in atry/catchblock. If the Google Calendar API returns an error (e.g., 400 Bad Request or 403 Forbidden), the exception bubbles up and gets lost in the unhandled promise mentioned above.// services/calendar/pod-calendar/src/outcomingClient.ts private async create(event: Event, calendar: ExternalCalendar): Promise<void> { const body = await this.convertBody(event) const calendarId = calendar.externalId if (calendarId !== undefined) { await this.rateLimiter.take(1) // If Google API rejects the payload, the error crashes the async flow silently. await this.calendar.events.insert({ calendarId, requestBody: body }) } }
-
Missing Logs for Bouncing Syncs:
Methods likegetTokenByEventreturn early if a token or calendar mapping is not found, but without throwing a warning or info log. This makes it impossible to distinguish between a missing token mapping and an actual Google API rejection.
Proposed Solution
To ensure the system works reliably and is transparent in case of outbound sync failures, proper error handling must be introduced:
-
Add
catchBlock to the Webhook Trigger:void OutcomingClient.push(ctx, accountClient, workspace, event, type).catch((err: any) => { ctx.error('Outcoming sync failed internally', { eventId: event.eventId, error: err }) })
-
Wrap Google API Calls in
try/catch:
InoutcomingClient.ts, API requests (insert,update) should trace exceptions and throw them.try { await this.calendar.events.insert({ calendarId, requestBody: body }) } catch (err: any) { this.ctx.error('Google API Insert Error', { calendarId, error: err.message, body }) throw err; }
-
Enhance Trace Logging:
Addctx.warnlogs whengetTokenByEventfails or when noExternalCalendaris linked.
Environment Details:
- Services Details:
pod-calendar,server-plugins/calendar-resources - Affected Files:
services/calendar/pod-calendar/src/main.ts,services/calendar/pod-calendar/src/outcomingClient.ts
Activity
huly-github-staging commentedon Feb 21, 2026
Connected to Huly®: UBERF-15627
fix(calendar): add error handling for outbound Google Calendar sync
fix(calendar): add error handling for outbound Google Calendar sync (h…
fix(calendar): add error handling for outbound Google Calendar sync (h…
Huly fixes (hcengineering#114)
fix(calendar): add error handling for outbound Google Calendar sync (h…