Skip to content

Fix Swift 6 strict concurrency violation in fetchReminders#3

Merged
steipete merged 1 commit into
openclaw:mainfrom
daveonkels:fix/swift6-concurrency-violation
Jan 11, 2026
Merged

Fix Swift 6 strict concurrency violation in fetchReminders#3
steipete merged 1 commit into
openclaw:mainfrom
daveonkels:fix/swift6-concurrency-violation

Conversation

@daveonkels
Copy link
Copy Markdown
Contributor

Problem

When running remindctl list, users encounter this error:

Incorrect actor executor assumption; expected 'RemindCore.RemindersStore' executor.

This is a Swift 6 strict concurrency violation caused by:

  1. Calling the actor-isolated item(from:) method from inside a non-isolated EventKit completion handler
  2. EKReminder objects not being Sendable, which violates data race safety requirements

Solution

Restructured the fetchReminders method in EventKitStore.swift to properly handle concurrency:

  1. Extract data in callback: All data is extracted from EKReminder objects inside the EventKit completion handler (where it's safe to access them)
  2. Use Sendable struct: Data is stored in a local Sendable struct called ReminderData
  3. Safe boundary crossing: Only Sendable data crosses the concurrency boundary
  4. Actor-isolated conversion: Conversion to ReminderItem happens on the actor using the safe data

This ensures:

  • All actor-isolated code runs on the correct executor
  • All data crossing concurrency boundaries is Sendable
  • Full compliance with Swift 6 strict concurrency checking

Testing

  • ✅ Built successfully with Swift 6.0
  • remindctl list - works without errors
  • remindctl list <name> - displays reminders correctly
  • remindctl show today/week - works as expected
  • remindctl list --json - JSON output verified
  • remindctl status - authorization check works

Changes

  • Modified Sources/RemindCore/EventKitStore.swift:206-252
  • Added local ReminderData struct for safe data transfer
  • Refactored fetchReminders to extract data before crossing concurrency boundary

Fixes the runtime error and ensures compatibility with Swift 6's strict concurrency model.

This fixes the "Incorrect actor executor assumption" error that occurred
when running `remindctl list`.

## Problem
The `fetchReminders` method was calling the actor-isolated `item(from:)`
method from inside a non-isolated EventKit completion handler. Additionally,
`EKReminder` objects are not `Sendable`, which violates Swift 6's strict
concurrency checking.

## Solution
Restructured `fetchReminders` to:
1. Extract all needed data from `EKReminder` objects inside the callback
   (where it's safe to access them)
2. Store that data in a local `Sendable` struct (`ReminderData`)
3. Pass the Sendable data across the concurrency boundary
4. Convert to `ReminderItem` on the actor using the safe data

This ensures all actor-isolated code runs on the correct executor and
all data crossing concurrency boundaries is Sendable.

## Testing
- Built successfully with Swift 6.0
- All commands tested: list, show, status
- JSON output verified
@steipete
Copy link
Copy Markdown
Collaborator

Thank you! Reviewing...

@steipete steipete merged commit ce8556d into openclaw:main Jan 11, 2026
1 check passed
@steipete
Copy link
Copy Markdown
Collaborator

Merged via #3 (Swift 6 strict concurrency-safe boundary). Thanks!

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