Hint at a stale Bluetooth serial port when the machine does not respond - #2228
Open
edwin-truthsearch-io wants to merge 1 commit into
Open
edwin-truthsearch-io wants to merge 1 commit into
edwin-truthsearch-io wants to merge 1 commit into
Conversation
On macOS a Bluetooth serial port can survive a system suspension as a stale device: /dev/cu.<machine> still exists and opens successfully, but there is no serial connection behind it any longer, so nothing is sent or received. The connect loop then repeats "connection timeout" forever while the user is left with empty readings and no indication of what to do. The port can only be re-established by removing the machine in the system Bluetooth settings and pairing it again (neither toggling Bluetooth nor reconnecting the device rebuilds it, and the Bluetooth daemon cannot be restarted under SIP). - counts the connect attempts of the Kaleido serial transport that opened the port but received no response from the machine and, after three of them, logs a hint and reports it to the user via the new unresponsive_handler - the hint is raised only once per unresponsive phase and re-armed by a successful connect, so a machine that is simply switched off does not repeat the message on every reconnect attempt Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 6, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses the second aspect of #2226 (and the long-standing #1705): recovering from a stale macOS Bluetooth serial port. This does not fix the stale port — it makes the state recognizable and tells the user what to do about it.
What happens today
After the Mac suspends with a Bluetooth serial machine connected, macOS can leave the serial device behind as a stale object.
/dev/cu.<machine>still exists andopen()still succeeds — instantly — but there is no serial connection behind it any more, so nothing is sent or received. The Kaleido connect loop then repeatsevery seven seconds, forever, while the user sits in front of empty readings with no indication of the cause or the cure.
What was measured
On macOS 26.6.2 with a Kaleido on Bluetooth SPP, in the stale state:
IOBluetoothDevice.closeConnection()isConnected()stays trueIOBluetoothDevice.openConnection()bluetoothdSo the pairing record owns the serial binding, and re-pairing is the only remedy available to a user. Worth noting for anyone reading #1705: toggling Bluetooth is not what fixes it — it only makes the unpaired machine visible again so it can be paired.
The change
The Kaleido serial transport counts connect attempts that opened the port but never received a response. After three, it logs a hint and reports it through a new optional
unresponsive_handler, which the canvas uses to tell the user:The hint is raised once per unresponsive phase and re-armed by a successful connect, so a machine that is simply switched off does not repeat the message on every reconnect attempt. An unresponsive machine and a stale port are indistinguishable from the application's side, which is why the wording is conditional rather than assertive.
Notes
AsyncComm, which has the identical failure mode, and I am happy to extend it if wanted.serial_connect(), as does Keep the machine connection alive across system standby #2225, so depending on merge order a small conflict resolution may be needed. The two changes are otherwise independent.start()re-arm it. Full suite 2376 passed / 7 skipped; ruff, pylint (10.00/10), mypy, pyright and codespell clean.🤖 Generated with Claude Code