fix(updater): explain failures in the user's terms, and make the macOS close button work - #160
Merged
Merged
Conversation
The grid could sit on "Running…" indefinitely — "0 rows · 12.0 s" and climbing — with no way out. `running` is cleared only when a `done` batch arrives or `api.stream` throws, and a wedged connection produces neither: the call resolves, then no batch ever comes. There is a connect timeout in the Postgres driver but no query/stream timeout anywhere. Adds a 20s stall watchdog to the table and query views. If no batch has arrived by then it clears `running`, shows "No response from the database — the connection may have dropped", and best-effort cancels the server-side handle so it isn't left running. The e2e test drives a genuinely stalled stream (the mock resolves the call and emits nothing) and fails when the watchdog is disabled, so it covers the behaviour rather than just the happy path.
Opening a table on a MongoDB connection could fail with
driver error: expected `db.<collection>.<method>(…)` or a `db.<helper>(…)` call
`TableDataTab` picks the dialect from `engine`, which is undefined while
the sessions and connections lists hydrate. `undefined !== "mongo"` fell
through to buildSql, so Postgres SQL went to the Mongo driver. The code
already carried a comment about this hazard — the subscription was fixed
so the engine resolves, but the undefined window was never guarded.
Now no query is built until the engine is known, and `run()` clears any
spinner instead of leaving one hanging. The effect re-runs once the
engine resolves, since `sql` is part of its key.
The mock backend gains a stall hook for the watchdog test. It lives in
`mockInvoke`, which `invoke` returns before reaching when `isTauri` is
true, so it cannot execute in the desktop app.
A failed check showed the raw Tauri message — "Could not fetch a valid release JSON from the remote". That is accurate for whoever wired the updater up and useless to whoever is running the app: it doesn't say what went wrong or what to do, and in this case the answer was simply "try again" (the failure was transient; the update worked after a restart). Maps the errors we can recognise onto plain guidance: - fetch/release JSON -> check your connection, GitHub may be down - signature/verify -> don't retry, download manually - network/timeout -> the download timed out - permission/denied -> move out of a read-only location The raw text moves into a collapsed "Technical details" block, so a bug report still carries it without the user having to read it first. The mapping lives in its own module with five tests, one of which uses the exact string the updater produced.
Closing the window with the red button appeared to do nothing — the app stayed running with no window, and Quit was the only way out. Two halves of the same platform default. macOS destroys the window on close rather than hiding it, and the app had no RunEvent handling, so: the window went away, the process lived on, and clicking the dock icon had nothing to restore. Now CloseRequested hides the window instead of destroying it, and Reopen shows it again — which is the macOS convention (close is not quit; the dock icon brings the app back). Both are macOS-only; other platforms keep their own behaviour, where closing the last window does exit.
oesukam
force-pushed
the
fix/updater-errors-and-macos-close
branch
from
September 5, 2026 18:59
d3e9ab1 to
ea4a00b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two unrelated fixes from the same report.
1. The update error said nothing useful
I checked the live endpoint first: it returns HTTP 200, valid JSON, v0.5.2, all 12 platforms signed. Nothing was wrong with the release — and indeed the update worked after a restart. It was a transient network failure.
Which is the point. The message is the raw Tauri string: accurate for whoever wired the updater up, useless for whoever is running the app. It names an internal artifact (
release JSON) and gives no indication that simply retrying would work.Now the recognisable failures map onto plain guidance:
The signature case matters most: retrying a signature failure is the wrong move, and the old message gave no hint of that.
The raw text moves into a collapsed Technical details block — still there for a bug report, no longer the first thing to parse.
Five unit tests, including one using the exact string you saw.
2. The macOS close button did nothing
Closing with the red button left the app running with no window; only Quit actually exited.
Two halves of the same platform default:
.run()with noRunEventhandling, so there was noReopenhook.Net effect: the window vanished, the process lived on, and clicking the dock icon had nothing to restore.
CloseRequestednow hides the window instead of destroying it, andReopenshows it again — the macOS convention that close is not quit. Both are#[cfg(target_os = "macos")]; other platforms keep their behaviour, where closing the last window does exit.Worth noting: my first attempt added only the
Reopenhandler. That compiles and looks right, butget_webview_window("main")returnsNoneafter the window is destroyed — it would have silently done nothing. The close interception is what makes the pair work.It also collided with an existing safety net. Startup already spawns a timer that shows the window if it is still hidden after 3s, guarding against a frontend that never paints. Hiding on close looks identical to "never shown", so closing the window within the first three seconds would have popped it straight back up. A flag now distinguishes the two, and it is
cfg-guarded so non-macOS builds (where closing still exits) stay warning-free.Verification
Typecheck clean · 370 unit tests (5 new) · 70/70 e2e · lint 2 warnings / 0 errors ·
cargo fmt+clippy -D warningsclean.The macOS behaviour needs a manual check — window lifecycle can't be exercised by CI or the browser-mode e2e suite. After merging, please confirm: red button hides the window, dock icon brings it back, ⌘Q still quits.