Skip to content

Watch crash fix: finish every background task in a wake - #2660

Merged
ps2 merged 1 commit into
LoopKit:next-devfrom
jeremybarnum:fix/watch-background-tasks
Nov 8, 2026
Merged

ps2 merged 1 commit into
LoopKit:next-devfrom
jeremybarnum:fix/watch-background-tasks

Conversation

@jeremybarnum

Copy link
Copy Markdown

Fixes a watch app crash that appeared with #2605.

Problem. watchOS can wake the watch app with several background tasks at once. ExtensionDelegate.handle(_:) returned from its loop after a phone message (WKWatchConnectivityRefreshBackgroundTask) or a snapshot, so any task after it in the same wake was never finished. watchOS ends the app when a task is released unfinished: "setTaskCompleted was never called on WKApplicationRefreshBackgroundTask".

This was harmless while the watch never asked for refreshes. Since #2605, the watch asks for one after each direct G7 reading. A refresh now often arrives together with the phone's context update, and the app is ended whenever the phone message comes first in the loop.

Seen on a watch. The app was ended 14 times in two days. In the device log, a phone message and a refresh arrived in one wake; the phone message was handled and the loop exited; the app was ended 1 ms later. In wakes where the refresh came first, both were finished and nothing happened.

Change. return becomes continue in those two cases, so the loop reaches every task. Phone-message tasks are still held until the session has no content pending, as before.

Testing. Built and run on a watch. A watch unit test, which hands the handler a refresh and a phone message in both orders, fails before the change and passes after it. It lives with the watch test target in #2545, since next-dev has no watch test target yet.

🤖 Generated with Claude Code

One wake can hand the watch app several background tasks at once, such as a refresh and a message from the phone. The handler stopped at the first phone message or snapshot, so a refresh later in the same wake was never finished, and watchOS ends the app when that happens.

Reading a G7 directly on the watch asks for a refresh after each reading, so a refresh now often shares a wake with the phone's regular updates. On a test watch the app was ended this way 14 times in two days. Each task is now handled in turn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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