Budibase/budibase · error · Error

Error authenticating with google sheets. ${json.error_descri

Error message

Error authenticating with google sheets. ${json.error_description}

What it means

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.

Source

Thrown at packages/server/src/integrations/googlesheets.ts:224

  private async fetchAccessToken(
    payload: AuthTokenRequest
  ): Promise<AuthTokenResponse> {
    const response = await fetch("https://www.googleapis.com/oauth2/v4/token", {
      method: "POST",
      body: JSON.stringify({
        ...payload,
        grant_type: "refresh_token",
      }),
      headers: {
        "Content-Type": "application/json",
      },
    })

    const json = await response.json()

    if (response.status !== 200) {
      throw new Error(
        `Error authenticating with google sheets. ${json.error_description}`
      )
    }

    return json
  }

  private async connect() {
    try {
      const bbCtx = context.getCurrentContext()
      let oauthClient = bbCtx?.googleSheets?.oauthClient

      if (!oauthClient) {
        await setupCreationAuth(this.config)

        // Initialise oAuth client
        const googleConfig = await configs.getGoogleDatasourceConfig()
        if (!googleConfig) {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Read the error_description in the message and match it to Google's OAuth error docs (invalid_grant, invalid_client, etc.)
  2. Re-run the Google Sheets OAuth authorization flow in the Budibase builder to get a fresh code/refresh token
  3. Verify the Google datasource config clientID/clientSecret in the workspace match the Google Cloud OAuth client
  4. If invalid_grant on refresh, the refresh token was revoked or expired — reconnect the datasource
  5. Check server can reach https://oauth2.googleapis.com (proxy/firewall)
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check config before attempting token exchange
function canAttemptAuth(config) {
  return Boolean(config && config.clientId && config.clientSecret && (config.code || config.refreshToken))
}

Try / catch

try {
  const json = await fetchAccessToken(...)
} catch (err) {
  if (err.message.startsWith('Error authenticating with google sheets.')) {
    if (err.message.includes('invalid_grant')) {
      // restart the OAuth consent flow for a fresh code/refresh token
    } else if (err.message.includes('invalid_client')) {
      // fix clientID/clientSecret in the Google datasource config
    }
  } else throw err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/b5fc2c04c8e4e6ac. Report an issue: GitHub.