juspay/hyperswitch · error · Error

User login call failed to fetch user info with status: "${re

Error message

User login call failed to fetch user info with status: "${response.status}" and message: "${response.body.error.message}"

What it means

Thrown by userInfo when GET /user (Authorization: Bearer {userInfoToken}) responds non-200. The user_info token is short-lived, so 401 expiry is the most common cause; 403/404 typically indicate the token lacks scope or the user record is gone.

Source

Thrown at cypress-tests/cypress/support/commands.js:6957

  }).then((response) => {
    logRequestId(response.headers["x-request-id"]);

    cy.wrap(response).then(() => {
      if (response.status === 200) {
        expect(response.body, "merchant_id").to.have.property("merchant_id").and
          .to.not.be.empty;
        expect(response.body, "organization_id").to.have.property("org_id").and
          .to.not.be.empty;
        expect(response.body, "profile_id").to.have.property("profile_id").and
          .to.not.be.empty;

        globalState.set("merchantId", response.body.merchant_id);
        globalState.set("organizationId", response.body.org_id);
        globalState.set("profileId", response.body.profile_id);

        globalState.set("userInfoToken", userInfoToken);
      } else {
        throw new Error(
          `User login call failed to fetch user info with status: "${response.status}" and message: "${response.body.error.message}"`
        );
      }
    });
  });
});

// Specific to routing tests
Cypress.Commands.add("ListMcaByMid", (globalState) => {
  const merchantId = globalState.get("merchantId");
  cy.request({
    method: "GET",
    url: `${globalState.get("baseUrl")}/account/${merchantId}/connectors`,
    headers: {
      "Content-Type": "application/json",
      "api-key": globalState.get("apiKey"),
      "X-Merchant-Id": merchantId,
    },

View on GitHub (pinned to 9b8b89dc37)

Solutions

  1. Re-run the whole login chain (userLogin → terminate2Fa → userInfo) immediately before any step that needs merchantId/profileId
  2. Confirm terminate2Fa succeeded and set userInfoToken (see error 69)
  3. Check x-request-id in server logs to distinguish expiry (401) from authorization (403)
  4. Verify globalState baseUrl matches the environment the user belongs to

Example fix

// before (stale token reused)
cy.userInfo(globalState);
// after
cy.userLogin(globalState);
cy.terminate2Fa(globalState);
cy.userInfo(globalState);
Defensive patterns

Strategy: retry

Validate before calling

// refresh the user_info token if it may be stale
const issuedAt = globalState.get('userInfoTokenIssuedAt');
if (!globalState.get('userInfoToken') || isOlderThanMinutes(issuedAt, 10)) {
  cy.userLogin(globalState);
  cy.terminate2Fa(globalState);
}
cy.userInfo(globalState);

Try / catch

cy.wrap(null)
  .then(() => cy.userInfo(globalState))
  .catch((e) => {
    if (/fetch user info with status: "401"/.test(e.message)) {
      // token expired mid-run: re-authenticate once and retry
      cy.userLogin(globalState);
      cy.terminate2Fa(globalState);
      return cy.userInfo(globalState);
    }
    throw e;
  });

Prevention

When it happens

Trigger: Long gap between terminate2Fa and userInfo so the bearer token expired (401); token invalid because terminate2Fa actually failed; user deleted or permissions changed mid-run; wrong baseUrl hitting another environment.

Common situations: Slow CI or many setup steps between login and /user call; reusing a recorded token across retries; environment mismatch (local token against staging).

Related errors


AI-assisted analysis of juspay/hyperswitch@9b8b89dc37 (2026-08-16). Data as JSON: /api/errors/e56be1caafc43c6e. Report an issue: GitHub.