From 0ca7b5368ca5981cf37388fd6d5023e415381803 Mon Sep 17 00:00:00 2001 From: Daniel Grossmann-Kavanagh Date: Tue, 20 Jan 2026 15:04:36 -0800 Subject: [PATCH] fix: Don't try to reconnect to realtime continuously on auth failure --- src/LoginManager.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/LoginManager.ts b/src/LoginManager.ts index 6b4e583..dbcb7e1 100644 --- a/src/LoginManager.ts +++ b/src/LoginManager.ts @@ -351,6 +351,10 @@ export class LoginManager extends Observable { const result = await this.endpointManager.validateAndSetEndpoints(timeoutMs); if (result.success && this.endpointManager.hasValidatedEndpoints()) { + // Clean up old PocketBase instance before creating new one + this.pb.cancelAllRequests(); + this.pb.realtime.unsubscribe(); + // Recreate PocketBase instance with new auth URL const pbLog = curryLog("[Pocketbase]", "debug"); this.pb = new PocketBase(this.endpointManager.getAuthUrl(), this.authStore); @@ -389,6 +393,7 @@ export class LoginManager extends Observable { logout() { this.pb.cancelAllRequests(); + this.pb.realtime.unsubscribe(); this.pb.authStore.clear(); this.user = undefined; this.notifyListeners(); @@ -549,10 +554,18 @@ export class LoginManager extends Observable { async login(provider: string): Promise { this.beforeLogin(); - const authData = await this.pb.collection("users").authWithOAuth2({ - provider: provider, - }); - return this.setup(authData, provider); + try { + const authData = await this.pb.collection("users").authWithOAuth2({ + provider: provider, + }); + return this.setup(authData, provider); + } catch (e) { + // Clean up realtime subscription to prevent reconnection loops + // authWithOAuth2 internally subscribes to @oauth2 via SSE, and if it fails, + // PocketBase's realtime client will keep trying to reconnect indefinitely + this.pb.realtime.unsubscribe(); + throw e; + } } async openLoginPage() {