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
- Reconnect using the originally intended Google account (use login_hint/authuser or a private window to force account choice).
- Clear the stored Google token/sub entry and re-run sign-in to bind the current account.
- If the original account was deleted, migrate the workspace data before reconnecting.
- 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
- Add prompt=select_account to the Google auth URL so users consciously pick the account
- Use login_hint with the stored account email when refreshing
- Clear stored sub/token entries when unlinking an account
- Check the account email in the token payload and show it to the user before binding
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
- GitLab account ID not expected.
- WordPress account ID not expected.
- Client ID inconsistent.
- Zendesk account ID not expected.
- Dropbox account ID not expected.
AI-assisted analysis of benweet/stackedit@6dce2a5e36 (2026-09-01).
Data as JSON: /api/errors/b2564e7121bec3c9.
Report an issue: GitHub.