diff --git a/src/app.h b/src/app.h index 276be60..a80485e 100644 --- a/src/app.h +++ b/src/app.h @@ -511,6 +511,7 @@ private: // and show the embedded-daemon start failure (binary/params/spawn) only once. Reset on connect. int daemon_wait_attempts_ = 0; bool daemon_start_error_shown_ = false; + int daemon_last_seen_crashes_ = 0; // surface each new embedded-daemon crash reason once float loading_timer_ = 0.0f; // spinner animation for loading overlay // Current page (sidebar navigation) diff --git a/src/app_network.cpp b/src/app_network.cpp index ea6e1cd..62bc5f1 100644 --- a/src/app_network.cpp +++ b/src/app_network.cpp @@ -300,6 +300,21 @@ void App::tryConnect() externalDetected ? "yes" : "no", daemon_controller_->crashCount(), daemon_controller_->lastError().empty() ? "(none)" : daemon_controller_->lastError().c_str()); + + // The embedded daemon can spawn successfully and then exit immediately (a missing runtime + // DLL, wrong architecture, corrupt binary, datadir lock, …). The crash monitor records a + // detailed reason (translated exit code + launch command + debug.log tail) in lastError(), + // but it runs on a background thread and was never shown — so the wallet looked like it was + // "stuck connecting" while the node silently died-and-respawned. Surface each new crash once. + const int crashes = daemon_controller_->crashCount(); + if (crashes > daemon_last_seen_crashes_) { + daemon_last_seen_crashes_ = crashes; + const std::string detail = daemon_controller_->lastError(); + if (!detail.empty()) { + connection_status_ = TR("sb_daemon_start_failed"); + ui::Notifications::instance().error(detail, 30.0f); + } + } } else { VERBOSE_LOGF("[connect #%d] No embedded daemon object (use_embedded=%s)\n", attempt, isUsingEmbeddedDaemon() ? "yes" : "no"); @@ -449,6 +464,7 @@ void App::onConnected() state_.daemon_initializing = false; // RPC is answering now; clear the "initializing" overlay daemon_wait_attempts_ = 0; // re-arm the port-busy / start-failure notifications daemon_start_error_shown_ = false; + daemon_last_seen_crashes_ = 0; // (onConnected resets the daemon's crash count too) connection_status_ = TR("connected"); // Reset crash counter on successful connection