Repository navigation
Desktop client gives up permanently after one failed reconnect attempt #174
Description
Summary
STOMPManager._on_close makes exactly one reconnect attempt. If that attempt raises,
connect() logs the exception and returns False to a caller that discards it, and nothing
ever retries. The process stays alive with no socket, the tray icon stays in its normal state,
and clipboard sync is dead until the user notices and relaunches the app by hand.
On my machines this ends sync for hours at a time. The most recent instance ran 8 hours before
anyone noticed, on a client that had been up for 3 days.
Where
stomp_ws/stomp_manager.py (3.2.0):
def _on_close(self):
self.is_connected = False
# Auto Reconnect
if not self.is_login_phase and not self.disconnected:
self.is_auto_reconnecting = True
if self.first_conn_lost:
self.notification_manager.notify(...)
self.first_conn_lost = False
time.sleep(RECONNECT_WS_TIMER) # seconds
self.connect() # <-- one attempt, return value discardedand the matching handler in connect():
except Exception as e:
msg = f"Failed to connect websocket: {e}"
logging.error(msg)
return Falsep2p/p2p_manager.py has the same shape.
Reproduce
- Log in with the desktop client and confirm sync works.
- Make the first reconnect attempt fail, and only that one — for example, drop the network
for slightly more thanRECONNECT_WS_TIMER(10 s) and restore it immediately after. - Restore the network fully and wait.
Expected: the client reconnects once the network is back.
Observed: the log ends at
ERROR - Connection to remote host was lost. - goodbye
ERROR - Failed to connect websocket: <error from the one attempt>
and nothing follows. Sync never returns. The tray icon is unchanged, so nothing on screen says
the client is offline.
Why one attempt is not enough
Every cause of a failed reconnect that I have hit is transient or self-healing, and each one
is permanent under the current code:
- The network is still down 10 s after the drop — a laptop waking from sleep, a Wi-Fi roam, a
router reboot. - The server is mid-restart.
- The bundled CA file the reconnect needs is missing (macOS: reconnect fails with [Errno 2] after ~3 days, because dirhelper deletes the bundled CA file #175:
certifi.where()inside the
PyInstaller one-file bundle on macOS).
Suggested fix
Retry until it succeeds, rather than once:
- Loop in
_on_closewhilenot self.is_connected and not self.disconnected, sleeping
RECONNECT_WS_TIMERbetween attempts — ideally with a bounded backoff so a long outage does
not hammer the server every 10 s. - Consider surfacing the state in the tray icon, so a client that is alive but not connected is
distinguishable from a healthy one without opening the log.
Related: #161 fixes a specific reconnect failure (server-side session expiry). This issue is
about the retry policy itself — with a loop in place, #161's case would also have recovered on
its own once the server came back, and vice versa the two are independent.
Environment
- ClipCascade 3.2.0, macOS build (
ClipCascade-Apple_macOS.ARM_M-Series.zip), Apple silicon. - Same code path on the Linux source build.
- Server 0.7.0, self-hosted, reached over
wss://through a reverse proxy.
Activity
voyager commentedon Oct 2, 2026
Same here on macOS (Apple silicon, desktop client against a self-hosted server behind Cloudflare). I close the lid every night; in the morning the client shows as connected but sync is dead in both directions. Re-logging on Android doesn't help; re-logging on the Mac fixes it immediately. Waking from sleep is my everyday trigger, so a retry loop with backoff (and a tray state for "not connected") would fix this for anyone who uses ClipCascade on a laptop. 👍
Sathvik-Rao commentedon Oct 25, 2026
#182