benweet/stackedit · error · Error

GitHub account ID not expected.

Error message

GitHub account ID not expected.

What it means

After a GitHub OAuth2 exchange, startOauth2 compares the authenticated user's id with the `sub` claim of the app token. If `${user.id}` !== sub, githubHelper throws at src/services/providers/helpers/githubHelper.js:104 because the GitHub account that authorized the app differs from the identity the token was minted for. This guards against binding workspace data to the wrong GitHub identity.

Source

Thrown at src/services/providers/helpers/githubHelper.js:104

    })).body;

    // Call the user info endpoint
    const user = (await networkSvc.request({
      method: 'GET',
      url: 'https://api.github.com/user',
      headers: {
        Authorization: `token ${accessToken}`,
      },
    })).body;
    userSvc.addUserInfo({
      id: `${subPrefix}:${user.id}`,
      name: user.login,
      imageUrl: user.avatar_url || '',
    });

    // Check the returned sub consistency
    if (sub && `${user.id}` !== sub) {
      throw new Error('GitHub account ID not expected.');
    }

    // Build token object including scopes and sub
    const token = {
      scopes,
      accessToken,
      name: user.login,
      sub: `${user.id}`,
      repoFullAccess: scopes.includes('repo'),
    };

    // Add token to github tokens
    store.dispatch('data/addGithubToken', token);
    return token;
  },
  async addAccount(repoFullAccess = false) {
    const token = await this.startOauth2(getScopes({ repoFullAccess }));
    badgeSvc.addBadge('addGitHubAccount');

View on GitHub (pinned to 6dce2a5e36)

Solutions

  1. Reconnect the provider while logged into the intended GitHub account (use a private window if multiple accounts are signed in).
  2. Clear the saved GitHub token and restart the OAuth flow so sub is derived from the fresh exchange.
  3. Verify the sub value fed into the token construction matches the account that completed authorization.
  4. Check the token's stored sub in app storage and remove mismatches before retrying.

Example fix

// before
if (sub && `${user.id}` !== sub) {
  throw new Error('GitHub account ID not expected.');
}
// after
if (sub && `${user.id}` !== sub) {
  throw new Error(`GitHub account ID not expected (authorized ${user.id}, expected ${sub}). Sign in with the correct GitHub account.`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

function savedGitHubSubMatches(sub) {
  const saved = readSavedProviderToken('github');
  return !saved || !saved.sub || saved.sub === sub;
}

Type guard

function isGitHubAccountMismatch(err) {
  return err instanceof Error && /account ID not expected/i.test(err.message);
}

Try / catch

try {
  await githubHelper.startOauth2(...);
} catch (err) {
  if (isGitHubAccountMismatch(err)) {
    clearStoredTokens('github');
    promptReauthWithCorrectAccount();
  }
}

Prevention

When it happens

Trigger: `${user.id}` !== sub in startOauth2: user authorized with a different GitHub account than the one associated with the token's sub; stale sub from a previously saved token reused in a new flow; multiple GitHub accounts in the browser.

Common situations: Developers with personal and work GitHub accounts switching between them; re-auth after account migration/renaming with cached tokens; shared-machine browser sessions.

Related errors


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