benweet/stackedit · error · Error

Zendesk account ID not expected.

Error message

Zendesk account ID not expected.

What it means

startOauth2 builds a per-instance unique sub (`${subdomain}/${user.id}`) from the Zendesk /users/me.json response and compares it with an optional expected sub. A mismatch throws 'Zendesk account ID not expected.', preventing a token from a different Zendesk instance or user from being bound to an existing entry.

Source

Thrown at src/services/providers/helpers/zendeskHelper.js:39

    const { accessToken } = await networkSvc.startOauth2(
      `https://${subdomain}.zendesk.com/oauth/authorizations/new`,
      {
        client_id: clientId,
        response_type: 'token',
        scope: 'read hc:write',
      },
      silent,
    );

    // Call the user info endpoint
    const { user } = await request({ accessToken }, {
      url: `https://${subdomain}.zendesk.com/api/v2/users/me.json`,
    });
    const uniqueSub = `${subdomain}/${user.id}`;

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

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

    // Add token to zendesk tokens
    store.dispatch('data/addZendeskToken', token);
    return token;
  },
  async addAccount(subdomain, clientId) {
    const token = await this.startOauth2(subdomain, clientId);
    badgeSvc.addBadge('addZendeskAccount');
    return token;

View on GitHub (pinned to 6dce2a5e36)

Solutions

  1. Reconnect through the original Zendesk subdomain and user account that matches the stored sub.
  2. If the subdomain legitimately changed, clear the stored sub and re-authorize to establish a new one.
  3. Sign out of other Zendesk sessions in the browser or use a private window to force the right account.
  4. Verify the stored sub string format (`subdomain/userId`) matches what current code builds.

Example fix

// before
const token = await zendeskHelper.startOauth2(code, sub, subdomain);
// after
try {
  const token = await zendeskHelper.startOauth2(code, sub, subdomain);
} catch (e) {
  if (e.message === 'Zendesk account ID not expected.') {
    // subdomain or user changed; rebind
    const token = await zendeskHelper.startOauth2(code, undefined, subdomain);
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const user = (await request({ accessToken }, { url: `https://${subdomain}.zendesk.com/api/v2/users/me.json` })).body.user;
const uniqueSub = `${subdomain}/${user.id}`;
if (expectedSub && uniqueSub !== expectedSub) {
  throw new Error(`Zendesk subdomain/user mismatch: expected ${expectedSub}, got ${uniqueSub}`);
}

Type guard

function isExpectedZendeskSub(user, subdomain, expectedSub) {
  return !expectedSub || `${subdomain}/${user.id}` === expectedSub;
}

Try / catch

try {
  const token = await zendeskHelper.startOauth2(code, sub, subdomain);
} catch (err) {
  if (err.message === 'Zendesk account ID not expected.') {
    // subdomain or user changed; clear stored sub and re-authorize
  } else throw err;
}

Prevention

When it happens

Trigger: OAuth callback (token) when the authenticated Zendesk user's subdomain/user.id composite differs from the stored sub — e.g. signing into a different Zendesk subdomain, or a different user on the same instance.

Common situations: Multiple Zendesk subdomains (company changed its Zendesk URL); agent vs admin accounts in the same browser; the subdomain config changed after the sub was stored; Zendesk user re-created with a new id.

Related errors


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