From 6084ed4d3c578153d79d06188245e1880e4a05ad Mon Sep 17 00:00:00 2001 From: LukeGus Date: Thu, 15 Oct 2026 21:40:07 -0500 Subject: [PATCH] fix: say the server is down and keep retrying instead of a database error (#1637) --- CHANGELOG.md | 2 ++ docker/nginx-https.conf | 5 ++++- docker/nginx.conf | 5 ++++- src/ui/auth/Auth.tsx | 3 ++- src/ui/locales/en.json | 4 ++-- src/ui/tests/auth/Auth.test.tsx | 18 ++++++++++++++++++ 6 files changed, 32 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3ba0fcab..522752685 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ - Synced plugins signed only by a key the server sent are no longer turned on by themselves - Two connects to the same host at once could overwrite each other's connection - Indonesian uses the same technical terms everywhere +- When the server was down or still starting, the login page said it could not connect to the database and stopped trying. It now says the server is not responding and continues on its own once the server is back +- nginx answered 404 instead of 502 while the backend was down - The Docker server crashed and restarted every few hours in ssh2's native crypto on Node 24 ## 26.10.1 diff --git a/docker/nginx-https.conf b/docker/nginx-https.conf index 182fee0e0..fbe592f9c 100644 --- a/docker/nginx-https.conf +++ b/docker/nginx-https.conf @@ -476,9 +476,12 @@ http { } error_page 500 502 503 504 /50x.html; + # Only nginx's own errors land here (the backend is down or too slow). + # There is no 50x page, so answer directly instead of a 404. location = /50x.html { - root /app/html; internal; + default_type application/json; + return 502 '{"error":"The Termix server is not responding"}'; } } } diff --git a/docker/nginx.conf b/docker/nginx.conf index 4f539e692..e529ce06c 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -445,9 +445,12 @@ http { } error_page 500 502 503 504 /50x.html; + # Only nginx's own errors land here (the backend is down or too slow). + # There is no 50x page, so answer directly instead of a 404. location = /50x.html { - root /app/html; internal; + default_type application/json; + return 502 '{"error":"The Termix server is not responding"}'; } } } diff --git a/src/ui/auth/Auth.tsx b/src/ui/auth/Auth.tsx index fcda8bb47..a6867a0ed 100644 --- a/src/ui/auth/Auth.tsx +++ b/src/ui/auth/Auth.tsx @@ -434,10 +434,11 @@ export function Auth({ onLogin }: AuthProps) { }) .catch(() => { if (cancelled) return; + // Past the first few tries, show the error but keep checking, so + // the page moves on by itself once the server is back. if (attemptNumber >= maxAttempts) { setDbConnectionFailed(true); setDbHealthChecking(false); - return; } const delay = Math.min(500 * 2 ** attemptNumber, 5000); retryTimer = setTimeout(() => { diff --git a/src/ui/locales/en.json b/src/ui/locales/en.json index 5d604369e..fa527ce28 100644 --- a/src/ui/locales/en.json +++ b/src/ui/locales/en.json @@ -1099,7 +1099,7 @@ "acceptNewKey": "Accept New Key & Continue" }, "errors": { - "databaseConnection": "Could not connect to the database", + "databaseConnection": "The Termix server is not responding", "embeddedServerFailed": "Termix's local server could not start", "unknownError": "Unknown error", "syncedHostMissing": "The synced host does not exist on the linked server", @@ -1126,7 +1126,7 @@ "messages": { "registrationDisabled": "You have no Termix account yet. Ask an admin to turn on Auto-create external accounts.", "userNotAllowed": "Your account is not authorized to register. Please contact an administrator.", - "databaseConnectionFailed": "Failed to connect to the database server", + "databaseConnectionFailed": "It may still be starting, or it stopped. This page keeps trying and continues on its own once the server is back.", "embeddedServerPortInUse": "Port {{port}} is already in use by another program. This is usually a Termix Docker container or a leftover Termix process from a previous session. Close it, then restart Termix.", "embeddedServerPortInUseUnknownPort": "One of the ports Termix needs is already in use by another program. Close whatever is using it, then restart Termix.", "embeddedServerOldDatabase": "Your local data is from Termix 2.8 or older and has to pass through 2.9 first. Install Termix 2.9.1, open it once so it can move your data, then update to this version again.", diff --git a/src/ui/tests/auth/Auth.test.tsx b/src/ui/tests/auth/Auth.test.tsx index de48b53d5..1c2ba0dfc 100644 --- a/src/ui/tests/auth/Auth.test.tsx +++ b/src/ui/tests/auth/Auth.test.tsx @@ -143,6 +143,24 @@ describe("Auth local desktop flow", () => { expect(mainAxios.getSetupRequired).not.toHaveBeenCalled(); }); + it("keeps checking after the server is unreachable and recovers on its own", async () => { + vi.useFakeTimers({ shouldAdvanceTime: true }); + try { + mainAxios.getSetupRequired.mockRejectedValue(new Error("502")); + renderAuth(); + await vi.advanceTimersByTimeAsync(20000); + expect(screen.getByText("errors.databaseConnection")).toBeTruthy(); + + mainAxios.getSetupRequired.mockResolvedValue({ setup_required: false }); + await vi.advanceTimersByTimeAsync(6000); + await waitFor(() => + expect(screen.queryByText("errors.databaseConnection")).toBeNull(), + ); + } finally { + vi.useRealTimers(); + } + }); + it("keeps register visible for normal web auth when registration is allowed", async () => { mainAxios.isElectron.mockReturnValue(false);