From e6f51168272d1638f941e3e986e1f04ef566cfb8 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Thu, 23 Jul 2026 07:25:22 +0200 Subject: [PATCH] fix: expired/revoked GitHub tokens weren't recognized as auth failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A dead PAT returns GitHub's actual 401 body ('Bad credentials'), which matched none of the auth_fail substrings — it fell into the 'API error, but authenticated' branch and never prompted the user to re-run vulp auth import. Added 401/'bad credentials' to the check. --- src/detail/settings_io.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/detail/settings_io.rs b/src/detail/settings_io.rs index 3108da4..d8d7a5c 100644 --- a/src/detail/settings_io.rs +++ b/src/detail/settings_io.rs @@ -68,8 +68,15 @@ pub fn poll_settings_rx(st: &mut St) { st.settings_err = None; } Some(Err(e)) => { + // A revoked/expired token doesn't surface any of the "no + // account configured" phrasing below — it comes back from the + // provider as an HTTP 401 with a body like GitHub's literal + // "Bad credentials", which needs its own check so the user gets + // steered toward `vulp auth import` instead of a generic error. + let lower = e.to_lowercase(); let auth_fail = e.contains("No GitHub account") || e.contains("no account") - || e.contains("no github") || e.contains("authentication"); + || e.contains("no github") || e.contains("authentication") + || lower.contains("bad credentials") || lower.contains(" 401 "); if auth_fail { st.settings = Some(settings_fallback(st)); st.settings_err = Some(e);