{"record":{"id":"f2c042e379aa2e45","repo":"espanso/espanso","slug":"unable-to-run-main-eventloop","errorCode":null,"errorMessage":"unable to run main eventloop","messagePattern":"unable to run main eventloop","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"espanso/src/cli/worker/mod.rs","lineNumber":168,"sourceCode":"    // terminate the worker if the daemon terminates\n    // This is needed to avoid \"dangling\" worker processes\n    // if the daemon crashes or is forcefully terminated.\n    if cli_args.is_present(\"monitor-daemon\") {\n        daemon_monitor::initialize_and_spawn(&paths.runtime, engine_exit_notify)\n            .expect(\"unable to initialize daemon monitor thread\");\n    }\n\n    secure_input::initialize_and_spawn(engine_secure_input_sender)\n        .expect(\"unable to initialize secure input watcher\");\n\n    eventloop\n        .run(Box::new(move |event| {\n            if let Err(error) = engine_ui_event_sender.send(event) {\n                error!(\"unable to send UIEvent to engine: {error}\");\n                panic!(\"broken UI->Engine channel\");\n            }\n        }))\n        .expect(\"unable to run main eventloop\");\n\n    info!(\"waiting for engine exit mode...\");\n    match engine_handle.join() {\n        Ok(mode) => match mode {\n            ExitMode::Exit => {\n                info!(\"exiting worker process...\");\n                WORKER_SUCCESS\n            }\n            ExitMode::ExitAllProcesses => {\n                info!(\"exiting worker process and daemon...\");\n                WORKER_EXIT_ALL_PROCESSES\n            }\n            ExitMode::RestartWorker => {\n                info!(\"exiting worker (to be restarted)\");\n                WORKER_RESTART\n            }\n        },\n        Err(err) => {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/espanso/espanso/blob/e6c3736675048026a057f1c4803d59242482fa7b/espanso/src/cli/worker/mod.rs#L150-L186","documentation":"eventloop.run() starts the main UI event loop, dispatching every UI event to the engine through a channel; this expect panics if run returns Err. Once this fails the worker cannot process events at all and must terminate.","triggerScenarios":"The platform event loop's run() returns an error — display connection lost mid-run (X server terminated, Wayland compositor restart), the UI subsystem hit a fatal error while pumping events, or the callback panicked (broken UI->Engine channel) propagating failure.","commonSituations":"Logging out or restarting the display server while espanso runs, X11/Wayland session crashes, desktop environment switching, or the engine thread having exited causing the send in the callback to fail and panic.","solutions":["Restart espanso after the display session is stable again (`espanso restart`).","Check whether the engine thread died first (broken UI->Engine channel panic) and fix the root engine failure seen earlier in logs.","Avoid restarting the display manager/compositor while espanso runs; stop espanso first.","Inspect platform logs for X11/Wayland disconnection errors and fix the session stability issue."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(err) = eventloop.run(Box::new(move |event| { ... })) {\n    error!(\"main eventloop terminated: {err}\");\n    // trigger supervised restart via the daemon\n    std::process::exit(1);\n}","preventionTips":["Stop espanso before logging out or restarting the display server.","Monitor the engine thread health; a dead engine causes the UI->Engine channel panic inside the callback.","Run the worker under daemon supervision so a fatal eventloop failure triggers a clean restart."],"tags":["rust","eventloop","ui","runtime-failure"],"backgroundTag":"module-init-failed","analyzedSha":"e6c3736675048026a057f1c4803d59242482fa7b","analyzedAt":"2026-09-06T15:16:34.240Z","contentChangedAt":"2026-09-06T15:16:34.240Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}