You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
aw-notify exits fatally when aw-server is unreachable at startup (crash-loops under desktop managers) #47
When aw-notify starts while aw-server is not yet accepting connections, it exits fatally instead of waiting/retrying. Under the desktop module manager (aw-tauri/aw-qt) this becomes a crash loop: the module is restarted with 2s/4s/8s backoff, gives up after 3 attempts, and the user gets a "module quit after 3 auto-restart attempts" dialog. On desktop the notification module is commonly (auto)started alongside aw-server, so a server that is slow to bind is enough to trigger it.
Connection refused when aw-notify polls /api/0/info.
Crash dialog: module quit after 3 auto-restart attempts within 10 minutes.
No new aw-notify log file is written for the crash.
The standalone aw-notify-rs v0.2.0 binary works for the same user.
Root cause
src/main.rs → run_app():
let client = aw_client_rust::blocking::AwClient::new("127.0.0.1", port, client_name).map_err(|e| anyhow!("Failed to create client: {}", e))?;
client.get_info()?;// <-- any connection error here is fatallet config = try_load_server_config(&client, config);if !config.enabled{/* opt-in gate */returnOk(());}
get_info()? propagates on connection-refused; main() then logs Fatal error: … and returns Err, so the process exits non-zero. The surrounding comment in the pre-opt-in code said "Wait for server to be ready (like Python's wait_for_start)", but the Rust rewrite has no actual wait/retry (the Python implementation did).
Suggested fix
Either of these would make startup robust:
Bounded wait-for-server at startup — poll get_info() with a short backoff for a bounded window (e.g. ~10–15s) before treating it as fatal. This window matters because the desktop manager's own retry budget is only 3 attempts, so the module must outlast a slow server bind itself.
Make the startup probe non-fatal — log the failure and continue; the existing server_monitor_thread already tracks SERVER_AVAILABLE and reconnects.
Option 1 matches the original Python wait_for_start behaviour and is the smallest change.
Repro
# With no aw-server listening on :5600
aw-notify --output-only
# -> "Fatal error: …" and a non-zero exit (no retry)
Already covered by #46; no competing PR needed. I reproduced the immediate fatal exit on master 8c5c1b1, then built and tested #46 at 15545489a660fb34e41c4481f414f87b9d123900 locally.
Verification: all 11 black-box opt-in/startup/heartbeat tests passed (including delayed server bind, transient 503 readiness failures, retry exhaustion, and settings read only after readiness), plus 20 Rust unit tests and 1 doctest. Clippy with warnings denied and formatting checks passed. The daemon retries /info five times with 1/2/4/8-second backoff; manual check-ins deliberately remain fail-fast.
Leaving this issue open until the fix lands. This verifies the startup race in the standalone binary, not that a released desktop bundle has been repaired. Also, the 15 seconds is the backoff budget, not a strict wall-clock deadline: requests retain the client timeout.
Verified fixed on master by #46, squash commit 87e83cc. Its Git tree (69e957a0fb76cdc83c4d6d10ee0597139a883298) exactly matches the PR head I tested above: delayed bind, transient 503 readiness failures, retry exhaustion, and settings read only after readiness are covered. Master Continuous Integration run 38800228072 and Lint and Format run 38800228074 both passed.
Closing this startup-only issue. This does not establish that a released desktop bundle includes the fix; ActivityWatch/activitywatch#1526 remains separate because disabled-module exits also need correct manager handling.
Activity
TimeToBuildBob commentedon Oct 15, 2026
Already covered by #46; no competing PR needed. I reproduced the immediate fatal exit on master
8c5c1b1, then built and tested #46 at15545489a660fb34e41c4481f414f87b9d123900locally.Verification: all 11 black-box opt-in/startup/heartbeat tests passed (including delayed server bind, transient 503 readiness failures, retry exhaustion, and settings read only after readiness), plus 20 Rust unit tests and 1 doctest. Clippy with warnings denied and formatting checks passed. The daemon retries
/infofive times with 1/2/4/8-second backoff; manual check-ins deliberately remain fail-fast.Leaving this issue open until the fix lands. This verifies the startup race in the standalone binary, not that a released desktop bundle has been repaired. Also, the 15 seconds is the backoff budget, not a strict wall-clock deadline: requests retain the client timeout.
TimeToBuildBob commentedon Oct 15, 2026
Verified fixed on master by #46, squash commit 87e83cc. Its Git tree (69e957a0fb76cdc83c4d6d10ee0597139a883298) exactly matches the PR head I tested above: delayed bind, transient 503 readiness failures, retry exhaustion, and settings read only after readiness are covered. Master Continuous Integration run 38800228072 and Lint and Format run 38800228074 both passed.
Closing this startup-only issue. This does not establish that a released desktop bundle includes the fix; ActivityWatch/activitywatch#1526 remains separate because disabled-module exits also need correct manager handling.