Skip to content

fix: avoid duplicate-key crash when listing events - #9

Open
bryansray wants to merge 2 commits into
Helmi:mainfrom
bryansray:fix/event-list-duplicate-identifiers
Open

bryansray wants to merge 2 commits into
Helmi:mainfrom
bryansray:fix/event-list-duplicate-identifiers

Conversation

@bryansray

Copy link
Copy Markdown

Summary

Fixes a crash in acal events list caused by duplicate calendarItemIdentifier values returned from EventKit.

Root cause

The EventKit-backed list path used Dictionary(uniqueKeysWithValues:) keyed only by calendarItemIdentifier. When EventKit returned multiple EKEvent values sharing that identifier, the command crashed with a fatal duplicate-key error.

What changed

  • replaced trap-prone dictionary construction with explicit deduplication in the EventKit adapter
  • deduplicate list rows by identifier plus occurrence timing instead of assuming one row per identifier
  • populate occurrenceStart for EventKit list results
  • mirror the same list dedupe behavior in the in-memory store

Repro

acal events list --from 2026-06-01 --to 2026-06-12

Previously this could fail with:

Swift/NativeDictionary.swift:792: Fatal error: Duplicate values for key: ...

Verification

  • swift build
  • swift build -c release
  • swift test --parallel could not be completed in this environment because XCTest was unavailable to SwiftPM

Notes

I did not attach this work to a shared td issue because this public repo does not appear to include a shared td project database; .todos/ and .td-root are gitignored and local-only.

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

Copy link
Copy Markdown

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 improves event deduplication in both InMemoryCalendarStore and EventKitAdapter by introducing a more comprehensive EventListIdentity struct that accounts for calendar IDs and occurrence start/end times. It also updates event serialization to include the occurrenceStart field. A compilation error was identified in EventKitAdapter.swift where .map is incorrectly called on a non-optional Date object; this should be replaced with a direct function call.

Comment thread Sources/EventKitAdapter/EventKitAdapter.swift Outdated
@bryansray
bryansray marked this pull request as ready for review April 6, 2026 15:35

Copy link
Copy Markdown

Still reproducible in acal 0.4.0 through MCP on macOS 27.2 (26B5091g).

Observed in a read-only test:

  • Calendar authorization reports full access.
  • list_calendars succeeds.
  • list_events for October 1–7, 2026, using explicit Vancouver -07:00 boundaries and limit: 3, terminates with Swift Fatal error: Duplicate values for key instead of returning events.

A couple of source-based details that may help callers until this lands:

  • Reducing limit cannot prevent this crash. The MCP handler applies it only after store.listEvents returns.
  • search_events also reaches the same list implementation, so changing to search does not bypass the duplicate-key construction.
  • Calendar filtering happens before the EventKit fetch. A single-calendar, one-day query might avoid multiple occurrences with the same identifier, but that is an untested workaround, not a reliable fix; filtering by calendar alone will not separate occurrences within a recurring series.

This confirms the failure still affects the released 0.4.0 after the permission fix in #11. I have not built or runtime-tested this PR's patch.

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.

2 participants