{"record":{"id":"b5fc2c04c8e4e6ac","repo":"Budibase/budibase","slug":"error-authenticating-with-google-sheets-json-er","errorCode":null,"errorMessage":"Error authenticating with google sheets. ${json.error_description}","messagePattern":"Error authenticating with google sheets\\. (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/integrations/googlesheets.ts","lineNumber":224,"sourceCode":"\n  private async fetchAccessToken(\n    payload: AuthTokenRequest\n  ): Promise<AuthTokenResponse> {\n    const response = await fetch(\"https://www.googleapis.com/oauth2/v4/token\", {\n      method: \"POST\",\n      body: JSON.stringify({\n        ...payload,\n        grant_type: \"refresh_token\",\n      }),\n      headers: {\n        \"Content-Type\": \"application/json\",\n      },\n    })\n\n    const json = await response.json()\n\n    if (response.status !== 200) {\n      throw new Error(\n        `Error authenticating with google sheets. ${json.error_description}`\n      )\n    }\n\n    return json\n  }\n\n  private async connect() {\n    try {\n      const bbCtx = context.getCurrentContext()\n      let oauthClient = bbCtx?.googleSheets?.oauthClient\n\n      if (!oauthClient) {\n        await setupCreationAuth(this.config)\n\n        // Initialise oAuth client\n        const googleConfig = await configs.getGoogleDatasourceConfig()\n        if (!googleConfig) {","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/integrations/googlesheets.ts#L206-L242","documentation":"fetchAccessToken exchanges the OAuth code/refresh token with Google's token endpoint. Any non-200 response (invalid code, expired refresh token, bad client secret, revoked grant) results in this error, with Google's error_description interpolated into the message. It signals the datasource cannot obtain a valid access token.","triggerScenarios":"Calling fetchAccessToken (via tokenResponse) when Google returns status != 200 — e.g. authorization code already redeemed/expired, refresh token revoked by the user, or mismatched clientID/clientSecret in the OAuth token request.","commonSituations":"Re-using an auth code from a completed OAuth flow; user revoked app access in their Google account; Google OAuth client credentials changed/rotated server-side; clock/network issues causing Google to reject the request; sandbox app in testing mode with expired grants.","solutions":["Read the error_description in the message and match it to Google's OAuth error docs (invalid_grant, invalid_client, etc.)","Re-run the Google Sheets OAuth authorization flow in the Budibase builder to get a fresh code/refresh token","Verify the Google datasource config clientID/clientSecret in the workspace match the Google Cloud OAuth client","If invalid_grant on refresh, the refresh token was revoked or expired — reconnect the datasource","Check server can reach https://oauth2.googleapis.com (proxy/firewall)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check config before attempting token exchange\nfunction canAttemptAuth(config) {\n  return Boolean(config && config.clientId && config.clientSecret && (config.code || config.refreshToken))\n}","typeGuard":null,"tryCatchPattern":"try {\n  const json = await fetchAccessToken(...)\n} catch (err) {\n  if (err.message.startsWith('Error authenticating with google sheets.')) {\n    if (err.message.includes('invalid_grant')) {\n      // restart the OAuth consent flow for a fresh code/refresh token\n    } else if (err.message.includes('invalid_client')) {\n      // fix clientID/clientSecret in the Google datasource config\n    }\n  } else throw err\n}","preventionTips":["Never reuse an authorization code; run a fresh OAuth flow each time","Refresh tokens proactively before expiry instead of on-demand","Verify clientID/clientSecret against Google Cloud Console after rotations","Notify users to re-link the datasource if they revoke access in their Google account"],"tags":["google-sheets","oauth","authentication","network"],"backgroundTag":"oauth-token-error","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}