From acff502f424635ec0b5ae4b56c46231913e36cbf Mon Sep 17 00:00:00 2001 From: Ramnique Singh <30795890+ramnique@users.noreply.github.com> Date: Fri, 8 May 2026 13:16:46 +0530 Subject: [PATCH] fix: stop Gmail sync from throwing "No refresh token is set" in rowboat mode In rowboat OAuth mode the OAuth2Client is built without a refresh_token because refreshes go through the api. google-auth-library's default 5-minute eagerRefreshThresholdMillis caused it to attempt a refresh whenever a Gmail call landed within 5 minutes of token expiry, throwing "No refresh token is set." before our proactive 60s-margin refresh could run. Disabling the eager window lets our getClient() refresh path own all refreshes as the comment intends. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../x/packages/core/src/knowledge/google-client-factory.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/x/packages/core/src/knowledge/google-client-factory.ts b/apps/x/packages/core/src/knowledge/google-client-factory.ts index 0c48ae37..aa47dbc2 100644 --- a/apps/x/packages/core/src/knowledge/google-client-factory.ts +++ b/apps/x/packages/core/src/knowledge/google-client-factory.ts @@ -293,9 +293,16 @@ export class GoogleClientFactory { * Rowboat OAuth2Client — no client_id/secret, no refresh_token. * Library auto-refresh is disabled by absence of refresh_token; our * proactive refresh in getClient() is the only refresh path. + * + * eagerRefreshThresholdMillis must be 0: the library defaults to a + * 5-minute window where it preemptively refreshes any token nearing + * expiry. Without a refresh_token on the client, that path throws + * "No refresh token is set." and the API call fails — even though + * our proactive refresh would have handled it on the next tick. */ private static createRowboatClient(tokens: OAuthTokens): OAuth2Client { const client = new OAuth2Client(); + client.eagerRefreshThresholdMillis = 0; client.setCredentials({ access_token: tokens.access_token, expiry_date: tokens.expires_at * 1000,