benweet/stackedit · error · Error

GitLab account ID not expected.

Error message

GitLab account ID not expected.

What it means

startOauth2 completes the GitLab OAuth2 flow: it exchanges the code for tokens, loads /user, and builds a unique sub (accountId-based identity string). If a previously stored 'sub' was supplied and the freshly returned identity does not match it, the helper throws 'GitLab account ID not expected.' to prevent attaching a different GitLab account's token to an existing entry.

Source

Thrown at src/services/providers/helpers/gitlabHelper.js:78

        scope: 'api',
      },
      silent,
    );

    // Call the user info endpoint
    const user = await request({ accessToken, serverUrl }, {
      url: 'user',
    });
    const uniqueSub = `${serverUrl}/${user.id}`;
    userSvc.addUserInfo({
      id: `${subPrefix}:${uniqueSub}`,
      name: user.username,
      imageUrl: user.avatar_url || '',
    });

    // Check the returned sub consistency
    if (sub && uniqueSub !== sub) {
      throw new Error('GitLab account ID not expected.');
    }

    // Build token object including scopes and sub
    const token = {
      accessToken,
      name: user.username,
      serverUrl,
      sub: uniqueSub,
    };

    // Add token to gitlab tokens
    store.dispatch('data/addGitlabToken', token);
    return token;
  },
  async addAccount(serverUrl, applicationId, sub = null) {
    const token = await this.startOauth2(serverUrl, applicationId, sub);
    badgeSvc.addBadge('addGitLabAccount');
    return token;

View on GitHub (pinned to 6dce2a5e36)

Solutions

  1. Log out of GitLab in the browser (or use a private window) and reconnect with the intended account.
  2. Clear the stored GitLab token/sub for this account in the app's data store, then re-run the OAuth flow to bind a fresh sub.
  3. Verify the GitLab instance URL/unique-sub construction matches what was stored previously.
  4. If refreshing, delete the stale refresh token so a full sign-in re-establishes the correct sub.

Example fix

// before
const token = await gitlabHelper.startOauth2(code, storedSub);
// after
try {
  const token = await gitlabHelper.startOauth2(code, storedSub);
} catch (e) {
  if (e.message === 'GitLab account ID not expected.') {
    // stored sub belongs to another account; reconnect with no expected sub
    const token = await gitlabHelper.startOauth2(code, undefined);
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before starting OAuth, confirm the browser session account matches the stored identity if possible
const stored = store.getters['data/gitlabTokensBySub'][expectedSub];
if (!stored) expectedSub = undefined; // no stale expectation to violate

Type guard

function isExpectedGitlabSub(uniqueSub, expectedSub) {
  return !expectedSub || uniqueSub === expectedSub;
}

Try / catch

try {
  const token = await gitlabHelper.startOauth2(code, expectedSub);
} catch (err) {
  if (err.message === 'GitLab account ID not expected.') {
    // clear stale token entry and re-run OAuth without expectedSub
  } else throw err;
}

Prevention

When it happens

Trigger: OAuth callback (token) or token refresh when the stored sub differs from the newly authenticated GitLab user's identity string — e.g. the user logged into a different GitLab account in the browser during the flow, or the stored sub is stale/corrupted.

Common situations: Multiple GitLab accounts (personal + work) in one browser session; self-hosted GitLab instance migrated users to new IDs; clearing app data while the OAuth session cookie still points at another account; subdomain/instance changed so the unique sub format no longer matches.

Related errors


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