From 814104aceaa0a5e9397c7c201b173133dbc70fff Mon Sep 17 00:00:00 2001 From: Chris Roberts <25612130+coderandhiker@users.noreply.github.com> Date: Fri, 18 Sep 2026 19:47:15 +0000 Subject: [PATCH] Fix stale remote server picker responses overwriting newer ones restartPicker is debounced, but a StartPicker call already in flight is not cancelled when the base path changes again. Typing the host before the port starts a picker for the default port; if that attempt is still failing when the real port is entered, its error lands after the newer picker succeeded and replaces the working state with a stale "failed to connect" error. Had the stale attempt succeeded instead, it would have replaced pickerId with a picker for the wrong url and leaked the newer one. Capture the base path before awaiting, and discard the response (releasing the picker it created) if the base path changed or the picker was disabled in the meantime, the same way checkValid already discards stale TryPick responses. --- .../src/lib/components/RemoteServerPicker.svelte | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/frontend/src/lib/components/RemoteServerPicker.svelte b/frontend/src/lib/components/RemoteServerPicker.svelte index 126b64d8..7cc355ff 100644 --- a/frontend/src/lib/components/RemoteServerPicker.svelte +++ b/frontend/src/lib/components/RemoteServerPicker.svelte @@ -52,11 +52,24 @@ const restartPicker = _.debounce(async () => { await stopPicker(); if (!disabled) { + const forBasePath = basePath; try { - pickerId = await StartPicker(basePath); + const newPickerId = await StartPicker(forBasePath); + // If the base path has changed since the request was made, + // or the picker has been disabled, ignore the response and release the picker + if (basePath !== forBasePath || disabled) { + await StopPicker(newPickerId); + return; + } + pickerId = newPickerId; currentBasePath = basePath; setupError = null; } catch (e) { + // If the base path has changed since the request was made, + // or the picker has been disabled, ignore the response + if (basePath !== forBasePath || disabled) { + return; + } setupError = e as string; pendingValidCheck = false; }