Skip to content

fix(calendar): preserve eventType when updating Focus Time, OOO, and Working Location events#319

Closed
RussellZager wants to merge 2 commits intogemini-cli-extensions:mainfrom
RussellZager:fix/preserve-event-type-on-update
Closed

fix(calendar): preserve eventType when updating Focus Time, OOO, and Working Location events#319
RussellZager wants to merge 2 commits intogemini-cli-extensions:mainfrom
RussellZager:fix/preserve-event-type-on-update

Conversation

@RussellZager
Copy link
Copy Markdown

@RussellZager RussellZager commented Apr 2, 2026

Summary

calendar.updateEvent uses events.update (PUT), which replaces the entire event resource. This causes two bugs:

  1. Focus Time / OOO / Working Location events fail with "Event type cannot be changed" — omitting eventType from the PUT body is interpreted as changing it to default
  2. Data loss on partial updates — fields not included in the request (summary, description, reminders, visibility, colorId, conferenceData, etc.) get silently wiped

Fix

Switch from events.update (PUT) to events.patch (PATCH). PATCH only modifies the fields present in the request body, preserving everything else. This matches the existing code comment (// patch semantics) and is the correct HTTP method for partial updates.

1 file changed, 9 insertions, 4 deletions.

Repro (bug 1)

  1. Create a Focus Time event in Google Calendar
  2. Update it via MCP (e.g., change start/end time)
  3. {"error": "Event type cannot be changed."}

Repro (bug 2)

  1. Create an event with a title, description, and custom reminders
  2. Update only the start/end time via MCP
  3. Title, description, and reminders are silently deleted

Ref

Test plan

  • Focus Time event: updated time, title and eventType preserved
  • Regular event: updated time, no field loss
  • Build passes (node esbuild.config.js)

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modifies the CalendarService to fetch existing event data before performing an update, ensuring that eventType and type-specific properties are preserved to prevent API errors. Feedback suggests using the patch method instead of update to improve efficiency by removing the extra fetch and to prevent accidental data loss for fields not included in the request body.

Comment on lines +730 to +733
const existing = await calendar.events.get({
calendarId: finalCalendarId,
eventId,
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using calendar.events.patch instead of calendar.events.update is a more efficient and safer approach for partial updates.

  1. Efficiency: patch only updates the fields provided in the request body, which eliminates the need for this extra get request to fetch and preserve the eventType and other properties.
  2. Safety: The current use of update (PUT semantics) replaces the entire resource. Any event fields not explicitly handled in UpdateEventInput (such as location, reminders, colorId, visibility, transparency, etc.) will be wiped out from the event on the server because they are missing from the requestBody.

Switching to patch solves the eventType issue while also preventing accidental data loss for all other fields. Note that the comment on line 735 already mentions "patch semantics," which further suggests that patch is the intended method.

…all event fields

The updateEvent method used events.update (PUT), which replaces the entire
event resource. Any field not explicitly included in the request body gets
wiped -- including summary, description, reminders, colorId, visibility,
recurrence, attachments, and conferenceData. Critically, it also rejects
non-default eventTypes (Focus Time, Out of Office, Working Location) with
Event type cannot be changed because omitting eventType is interpreted
as changing it to default.

Switch to events.patch (PATCH), which only modifies the fields present in
the request body and preserves everything else. This is the correct HTTP
semantics for partial updates and matches the methods documented intent
(patch semantics comment was already in the code).

Fixes updating Focus Time, Out of Office, and Working Location events.
Also fixes data loss when updating any event with only a subset of fields
(e.g., changing only the time without re-specifying the title).

Ref: https://developers.google.com/calendar/api/v3/reference/events/patch
@RussellZager RussellZager force-pushed the fix/preserve-event-type-on-update branch from 3679be0 to 570520f Compare April 2, 2026 16:36
…all event fields

The updateEvent method used events.update (PUT), which replaces the entire
event resource. Any field not explicitly included in the request body gets
wiped -- including summary, description, reminders, colorId, visibility,
recurrence, attachments, and conferenceData. Critically, it also rejects
non-default eventTypes (Focus Time, Out of Office, Working Location) with
Event type cannot be changed because omitting eventType is interpreted
as changing it to default.

Switch to events.patch (PATCH), which only modifies the fields present in
the request body and preserves everything else. This is the correct HTTP
semantics for partial updates and matches the methods documented intent
(patch semantics comment was already in the code).

Changes:
- Replace events.update with events.patch in CalendarService.ts
- Remove unnecessary type cast on applyMeetAndAttachments call
- Update all updateEvent test mocks from events.update to events.patch
- Add test verifying Focus Time events are preserved on partial update

Ref: https://developers.google.com/calendar/api/v3/reference/events/patch
@galuszkak
Copy link
Copy Markdown
Contributor

I did address also this in #316

@RussellZager
Copy link
Copy Markdown
Author

Thanks @galuszkak — just saw #316 covers this as part of the larger refactor. Closing as duplicate. The core fix is the same: events.update (PUT) → events.patch (PATCH) to preserve eventType and avoid silent field loss on partial updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants