benweet/stackedit · error · Error

Google account ID not expected.

Error message

Google account ID not expected.

What it means

After validating the ID token's audience, startOauth2 compares the token's 'sub' claim (Google's stable user ID) against an optional expected sub. When an expected sub was supplied and `${body.sub}` !== sub, it throws 'Google account ID not expected.' — the signed-in Google account differs from the one already associated with this entry.

Source

Thrown at src/services/providers/helpers/googleHelper.js:146

      silent,
    );

    // Call the token info endpoint
    const { body } = await networkSvc.request({
      method: 'POST',
      url: 'https://www.googleapis.com/oauth2/v3/tokeninfo',
      params: {
        access_token: accessToken,
      },
    }, true);

    // Check the returned client ID consistency
    if (body.aud !== clientId) {
      throw new Error('Client ID inconsistent.');
    }
    // Check the returned sub consistency
    if (sub && `${body.sub}` !== sub) {
      throw new Error('Google account ID not expected.');
    }

    // Build token object including scopes and sub
    const existingToken = store.getters['data/googleTokensBySub'][body.sub];
    const token = {
      scopes,
      accessToken,
      expiresOn: Date.now() + (expiresIn * 1000),
      idToken,
      sub: body.sub,
      name: (existingToken || {}).name || 'Someone',
      isLogin: !store.getters['workspace/mainWorkspaceToken'] &&
        scopes.includes('https://www.googleapis.com/auth/drive.appdata'),
      isSponsor: false,
      isDrive: scopes.includes('https://www.googleapis.com/auth/drive') ||
        scopes.includes('https://www.googleapis.com/auth/drive.file'),
      isBlogger: scopes.includes('https://www.googleapis.com/auth/blogger'),
      isPhotos: scopes.includes('https://www.googleapis.com/auth/photos'),

View on GitHub (pinned to 6dce2a5e36)

Solutions

  1. Reconnect using the originally intended Google account (use login_hint/authuser or a private window to force account choice).
  2. Clear the stored Google token/sub entry and re-run sign-in to bind the current account.
  3. If the original account was deleted, migrate the workspace data before reconnecting.
  4. Verify the expected sub passed into startOauth2 is the correct stored value and not from another account's record.

Example fix

// before
const token = await googleHelper.refreshToken(refreshToken, sub);
// after
try {
  const token = await googleHelper.refreshToken(refreshToken, sub);
} catch (e) {
  if (e.message === 'Google account ID not expected.') {
    // wrong Google account; force a fresh sign-in
    const token = await googleHelper.signin(newSubHint);
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// decode the ID token client-side before validating
const payload = JSON.parse(atob(idToken.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
if (expectedSub && String(payload.sub) !== expectedSub) {
  // wrong Google account: restart sign-in with account chooser (prompt=select_account)
}

Type guard

function isExpectedGoogleSub(idTokenBody, expectedSub) {
  return !expectedSub || `${idTokenBody.sub}` === expectedSub;
}

Try / catch

try {
  const token = await googleHelper.startOauth2(code, sub, clientId);
} catch (err) {
  if (err.message === 'Google account ID not expected.') {
    // prompt user to pick the originally linked Google account or clear the binding
  } else throw err;
}

Prevention

When it happens

Trigger: signin, token (callback), or refreshToken where the Google account completing the flow (or holding the refresh token) has a different sub than the stored one — e.g. switching Google accounts in the browser, or a refresh token belonging to another user.

Common situations: Multiple Google accounts logged into the browser; account selector picking the wrong profile; refresh after the original account was suspended/deleted; stored sub from a previous database copied across workspaces.

Related errors


AI-assisted analysis of benweet/stackedit@6dce2a5e36 (2026-09-01). Data as JSON: /api/errors/b2564e7121bec3c9. Report an issue: GitHub.