From 2268350ccaf55fe08b29f340716356dc51b9d9ff Mon Sep 17 00:00:00 2001 From: lucaronin Date: Tue, 24 Feb 2026 10:18:50 +0100 Subject: [PATCH 1/4] fix: surface actual error messages in GitHub OAuth login flow The frontend was swallowing Tauri backend errors (which are strings, not Error instances) and always showing generic "Failed to start login." Now the actual error message is displayed. Also adds User-Agent header to device flow requests, a clear error message for 404 responses, and a test for the 404 case. Co-Authored-By: Claude Opus 4.6 --- src-tauri/src/github.rs | 28 +++++++++++++++++++++++++++- src/components/SettingsPanel.tsx | 4 ++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/github.rs b/src-tauri/src/github.rs index a4f9172e..fa1bc841 100644 --- a/src-tauri/src/github.rs +++ b/src-tauri/src/github.rs @@ -175,14 +175,22 @@ async fn github_device_flow_start_with_base(base_url: &str) -> Result { stopPolling() setOauthStatus('error') - setErrorMessage(err instanceof Error ? err.message : 'Polling failed.') + setErrorMessage(typeof err === 'string' ? err : err instanceof Error ? err.message : 'Polling failed.') }) } catch (err) { setOauthStatus('error') - setErrorMessage(err instanceof Error ? err.message : 'Failed to start login.') + setErrorMessage(typeof err === 'string' ? err : err instanceof Error ? err.message : 'Failed to start login.') } }, [onConnected, stopPolling]) From 79fe2d9e6d9cc2cdad0456194b0f7d7130351db1 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Tue, 24 Feb 2026 10:29:23 +0100 Subject: [PATCH 2/4] fix: improve device flow 404 error with setup instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GitHub App (Ov23liCuBz7Z5hKk6T8c) does not have Device authorization flow enabled — GitHub returns 404. The error message now includes specific setup steps so the user can fix the configuration. Co-Authored-By: Claude Opus 4.6 --- src-tauri/src/github.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/github.rs b/src-tauri/src/github.rs index fa1bc841..6f930fa5 100644 --- a/src-tauri/src/github.rs +++ b/src-tauri/src/github.rs @@ -2,7 +2,9 @@ use serde::{Deserialize, Serialize}; use std::path::Path; use std::process::Command; -/// GitHub OAuth App client ID. Replace with your registered GitHub App's client_id. +/// GitHub App client ID for OAuth device flow. +/// To set up: GitHub Settings → Developer settings → GitHub Apps → New GitHub App. +/// Enable "Device authorization flow" under Optional features. Webhook can be disabled. const GITHUB_CLIENT_ID: &str = "Ov23liCuBz7Z5hKk6T8c"; #[derive(Debug, Serialize, Deserialize, Clone)] @@ -186,7 +188,8 @@ async fn github_device_flow_start_with_base(base_url: &str) -> Result Date: Tue, 24 Feb 2026 10:30:53 +0100 Subject: [PATCH 3/4] test: add tests for string error display and double-click prevention Tauri invoke errors are strings (not Error instances). The new test verifies the frontend displays the actual backend error message. Also tests that the login button is disabled during the OAuth flow. Co-Authored-By: Claude Opus 4.6 --- src/components/SettingsPanel.test.tsx | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/components/SettingsPanel.test.tsx b/src/components/SettingsPanel.test.tsx index 39cd7789..71aac1a7 100644 --- a/src/components/SettingsPanel.test.tsx +++ b/src/components/SettingsPanel.test.tsx @@ -291,5 +291,56 @@ describe('SettingsPanel', () => { ) expect(screen.getByText(/Connect your GitHub account/)).toBeInTheDocument() }) + + it('displays the actual backend error string when device flow start fails', async () => { + mockInvokeFn.mockImplementation(async (cmd: string) => { + if (cmd === 'github_device_flow_start') { + // Tauri invoke rejects with a plain string, not an Error instance + throw 'GitHub device flow not available. Ensure a GitHub App is registered.' + } + return null + }) + + render( + + ) + + fireEvent.click(screen.getByTestId('github-login')) + + await waitFor(() => { + expect(screen.getByTestId('github-error')).toHaveTextContent( + 'GitHub device flow not available. Ensure a GitHub App is registered.' + ) + }) + }) + + it('prevents double-click by disabling button during login flow', async () => { + let resolveStart: ((v: unknown) => void) | null = null + mockInvokeFn.mockImplementation(async (cmd: string) => { + if (cmd === 'github_device_flow_start') { + return new Promise(r => { resolveStart = r }) + } + return null + }) + + render( + + ) + + const loginBtn = screen.getByTestId('github-login') as HTMLButtonElement + fireEvent.click(loginBtn) + + // Button should be disabled while waiting + await waitFor(() => { + expect(loginBtn.disabled).toBe(true) + }) + + // Clean up + resolveStart?.({ + device_code: 'dc', user_code: 'UC-1234', + verification_uri: 'https://github.com/login/device', + expires_in: 900, interval: 5, + }) + }) }) }) From 209821ffdd24198cea4e65a89fcd2bfd413521ed Mon Sep 17 00:00:00 2001 From: lucaronin Date: Tue, 24 Feb 2026 11:43:03 +0100 Subject: [PATCH 4/4] fix: use correct GitHub OAuth App client_id for device flow The previous client_id pointed to a GitHub App that did not have device authorization flow enabled, causing "failed to start login" errors. Switch to the refactoringhq OAuth App (Ov23liwee215tDMs9u4L) which supports device flow. Co-Authored-By: Claude Opus 4.6 --- src-tauri/src/github.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/github.rs b/src-tauri/src/github.rs index 6f930fa5..cda8fe1d 100644 --- a/src-tauri/src/github.rs +++ b/src-tauri/src/github.rs @@ -5,7 +5,7 @@ use std::process::Command; /// GitHub App client ID for OAuth device flow. /// To set up: GitHub Settings → Developer settings → GitHub Apps → New GitHub App. /// Enable "Device authorization flow" under Optional features. Webhook can be disabled. -const GITHUB_CLIENT_ID: &str = "Ov23liCuBz7Z5hKk6T8c"; +const GITHUB_CLIENT_ID: &str = "Ov23liwee215tDMs9u4L"; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct GithubRepo {