Summary
On macOS the client builds its WebSocket SSL context from certifi.where(). In the one-file
PyInstaller bundle that path resolves inside the extraction directory,
/var/folders/<...>/T/_MEI<random>/certifi/cacert.pem. /usr/libexec/dirhelper, run by
/System/Library/LaunchDaemons/com.apple.bsd.dirhelper.plist at 03:35 daily with
CLEAN_FILES_OLDER_THAN_DAYS=3, deletes files under /var/folders/.../T/ that have not been
accessed in three days — including the contents of an _MEI directory belonging to a
still-running process. Apple documents the behaviour on _CS_DARWIN_USER_TEMP_DIR: files
there "may be cleaned (removed) by the system if they are not accessed in 3 days."
certifi.where() is only called on the (re)connect path, so a long-lived client reads that file
for the first time in days exactly when it needs to reconnect, and by then it is gone:
ERROR - Connection to remote host was lost. - goodbye
ERROR - Failed to connect websocket: [Errno 2] No such file or directory
Combined with the single-attempt reconnect (#174), this ends clipboard sync
permanently, with the process still running and the tray icon unchanged.
Where
utils/ssl_helper.py (3.2.0):
if PLATFORM == MACOS:
ctx = ssl.create_default_context(cafile=certifi.where())
return {"context": ctx}
The Linux and Windows paths return None and use the library/OS default, so they are unaffected.
Reproduce
Leave the macOS app running for more than three days without a reconnect, then break and restore
the connection. The evidence is visible without waiting, on any machine where the app has been
up that long:
$ for d in /var/folders/*/*/T/_MEI*; do
printf '%s mtime=%s cacert=%s\n' "$d" "$(stat -f '%Sm' "$d")" \
"$(test -f "$d/certifi/cacert.pem" && echo present || echo MISSING)"
done
/var/folders/…/T/_MEIB8SvLX mtime=Sep 8 03:35:04 2026 cacert=MISSING
/var/folders/…/T/_MEIiqFfIl mtime=Sep 2 03:35:04 2026 cacert=MISSING
/var/folders/…/T/_MEIMvyX83 mtime=Sep 10 03:35:28 2026 cacert=MISSING
The ~03:35 mtimes are the daily purge. The app in question had started 3.2 days before its
reconnect failed.
Suggested fix
Any of these removes the failure; the first is the smallest:
- Resolve and read the CA bundle once at startup — e.g. load it into an
SSLContext in
__init__ and reuse that context — so the reconnect does not depend on a file that may have
been deleted since. This does not survive a purge plus a context rebuild, but it removes
the common case.
- Copy the bundle out of
sys._MEIPASS into a directory macOS does not purge (e.g. under
~/Library/Application Support/ClipCascade/) on first run, and point cafile there.
- Fall back to the platform default when the file is gone:
if PLATFORM == MACOS:
path = certifi.where()
ctx = ssl.create_default_context(cafile=path) if os.path.isfile(path) \
else ssl.create_default_context()
return {"context": ctx}
Worth noting for whichever is chosen: the same reasoning applies to any other data file the
bundle reads lazily rather than at startup.
Environment
- ClipCascade 3.2.0, macOS build (
ClipCascade-Apple_macOS.ARM_M-Series.zip), Apple silicon,
launched at login and left running for days.
- Server 0.7.0, self-hosted, reached over
wss:// through a reverse proxy with a public CA
certificate (no ssl_ca_bundle configured, so the certifi branch is the one taken).
Summary
On macOS the client builds its WebSocket SSL context from
certifi.where(). In the one-filePyInstaller bundle that path resolves inside the extraction directory,
/var/folders/<...>/T/_MEI<random>/certifi/cacert.pem./usr/libexec/dirhelper, run by/System/Library/LaunchDaemons/com.apple.bsd.dirhelper.plistat 03:35 daily withCLEAN_FILES_OLDER_THAN_DAYS=3, deletes files under/var/folders/.../T/that have not beenaccessed in three days — including the contents of an
_MEIdirectory belonging to astill-running process. Apple documents the behaviour on
_CS_DARWIN_USER_TEMP_DIR: filesthere "may be cleaned (removed) by the system if they are not accessed in 3 days."
certifi.where()is only called on the (re)connect path, so a long-lived client reads that filefor the first time in days exactly when it needs to reconnect, and by then it is gone:
Combined with the single-attempt reconnect (#174), this ends clipboard sync
permanently, with the process still running and the tray icon unchanged.
Where
utils/ssl_helper.py(3.2.0):The Linux and Windows paths return
Noneand use the library/OS default, so they are unaffected.Reproduce
Leave the macOS app running for more than three days without a reconnect, then break and restore
the connection. The evidence is visible without waiting, on any machine where the app has been
up that long:
The ~03:35 mtimes are the daily purge. The app in question had started 3.2 days before its
reconnect failed.
Suggested fix
Any of these removes the failure; the first is the smallest:
SSLContextin__init__and reuse that context — so the reconnect does not depend on a file that may havebeen deleted since. This does not survive a purge plus a context rebuild, but it removes
the common case.
sys._MEIPASSinto a directory macOS does not purge (e.g. under~/Library/Application Support/ClipCascade/) on first run, and pointcafilethere.Worth noting for whichever is chosen: the same reasoning applies to any other data file the
bundle reads lazily rather than at startup.
Environment
ClipCascade-Apple_macOS.ARM_M-Series.zip), Apple silicon,launched at login and left running for days.
wss://through a reverse proxy with a public CAcertificate (no
ssl_ca_bundleconfigured, so thecertifibranch is the one taken).