{"record":{"id":"b5a04bc3a2ee3ade","repo":"benweet/stackedit","slug":"wordpress-account-id-not-expected","errorCode":null,"errorMessage":"WordPress account ID not expected.","messagePattern":"WordPress account ID not expected\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/services/providers/helpers/wordpressHelper.js","lineNumber":41,"sourceCode":"    // Get an OAuth2 code\n    const { accessToken, expiresIn } = await networkSvc.startOauth2(\n      'https://public-api.wordpress.com/oauth2/authorize',\n      {\n        client_id: clientId,\n        response_type: 'token',\n        scope: 'global',\n      },\n      silent,\n    );\n\n    // Call the user info endpoint\n    const body = await request({ accessToken }, {\n      url: 'https://public-api.wordpress.com/rest/v1.1/me',\n    });\n\n    // Check the returned sub consistency\n    if (sub && `${body.ID}` !== sub) {\n      throw new Error('WordPress account ID not expected.');\n    }\n    // Build token object including scopes and sub\n    const token = {\n      accessToken,\n      expiresOn: Date.now() + (expiresIn * 1000),\n      name: body.display_name,\n      sub: `${body.ID}`,\n    };\n    // Add token to wordpress tokens\n    store.dispatch('data/addWordpressToken', token);\n    return token;\n  },\n  async refreshToken(token) {\n    const { sub } = token;\n    const lastToken = store.getters['data/wordpressTokensBySub'][sub];\n\n    if (lastToken.expiresOn > Date.now() + tokenExpirationMargin) {\n      return lastToken;","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/benweet/stackedit/blob/6dce2a5e36b755a0c244522b48a06c91a2df0f59/src/services/providers/helpers/wordpressHelper.js#L23-L59","documentation":"startOauth2 fetches the WordPress.com user profile (rest/v1.1/me) and compares `${body.ID}` with an optional expected sub. On mismatch it throws 'WordPress account ID not expected.' so a token for a different WordPress.com account is never attached to an existing entry.","triggerScenarios":"OAuth callback (token) or refreshToken when the authenticated WordPress.com user's numeric ID differs from the stored sub — e.g. the browser session belongs to another WordPress account, or a refresh token was issued to a different user.","commonSituations":"Multiple WordPress.com accounts in one browser; shared machine where a colleague's WordPress session is active; stored sub copied from another environment; WordPress account migration/merge changing the ID mapping.","solutions":["Sign out of WordPress.com in the browser (or use a private window) and reconnect with the intended account.","Clear the stored WordPress token/sub and re-run the OAuth flow to bind the current account.","Verify the sub value passed into startOauth2 matches the stored token's sub field.","If refreshing, delete the stale refresh token and perform a fresh authorization."],"exampleFix":"// before\nconst token = await wordpressHelper.startOauth2(code, sub);\n// after\ntry {\n  const token = await wordpressHelper.startOauth2(code, sub);\n} catch (e) {\n  if (e.message === 'WordPress account ID not expected.') {\n    // reconnect without expecting a previous sub\n    const token = await wordpressHelper.startOauth2(code, undefined);\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"const body = await request({ accessToken }, { url: 'https://public-api.wordpress.com/rest/v1.1/me' });\nif (expectedSub && `${body.ID}` !== expectedSub) {\n  throw new Error(`WordPress account mismatch: expected ${expectedSub}, got ${body.ID}`);\n}","typeGuard":"function isExpectedWordPressId(meBody, expectedSub) {\n  return !expectedSub || `${meBody.ID}` === expectedSub;\n}","tryCatchPattern":"try {\n  const token = await wordpressHelper.startOauth2(code, sub);\n} catch (err) {\n  if (err.message === 'WordPress account ID not expected.') {\n    // re-authenticate with the correct WordPress.com account\n  } else throw err;\n}","preventionTips":["Show the authenticated display_name/ID to the user before committing the token","Force account selection by signing out of WordPress.com before re-linking","Delete refresh tokens when unlinking so stale identities cannot resurface","Never copy subs between test and production data stores"],"tags":["wordpress","oauth2","account-mismatch","token"],"backgroundTag":"oauth-account-mismatch","analyzedSha":"6dce2a5e36b755a0c244522b48a06c91a2df0f59","analyzedAt":"2026-09-01T00:49:23.866Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}