subclasses (ConnectionResetError, BrokenPipeError). When a client
becomes unreachable mid-generation (laptop sleeps, drops off WiFi),
the OS raises OSError: [Errno 113] No route to host (EHOSTUNREACH),
which is a sibling of ConnectionError, not a subclass. It therefore
escaped the handler, propagated through publish_loop, and could crash
the entire server over a single dead client.
After a frontend update (e.g. nightly build), browsers could load
outdated cached index.html and JS/CSS chunks, causing dynamically
imported modules to fail with MIME type errors and vite:preloadError.
Hard refresh (Ctrl+Shift+R) was insufficient to fix the issue because
Cache-Control: no-cache still allows the browser to cache and
revalidate via ETags. aiohttp's FileResponse auto-generates ETags
based on file mtime+size, which may not change after pip reinstall,
so the browser gets 304 Not Modified and serves stale content.
Clearing ALL site data in DevTools did fix it, confirming the HTTP
cache was the root cause.
The fix changes:
- index.html: no-cache -> no-store, must-revalidate
- JS/CSS/JSON entry points: no-cache -> no-store
no-store instructs browsers to never cache these responses, ensuring
every page load fetches the current index.html with correct chunk
references. This is a small tradeoff (~5KB re-download per page load)
for guaranteed correctness after updates.