juspay/hyperswitch · error · Error

No token received from login

Error message

No token received from login

What it means

Thrown by the userLogin command when POST /user/v2/signin?token_only=true returns 200 with token_type 'totp' but the token field is falsy. Note the chai assertion directly above already requires a non-empty 'token' property, so in practice that expect fails first with its own message; this throw is a defensive fallback for edge cases (e.g. non-string falsy token).

Source

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

    method: "POST",
    url: url,
    headers: {
      "Content-Type": "application/json",
    },
    body: signinBody,
    failOnStatusCode: false,
  }).then((response) => {
    logRequestId(response.headers["x-request-id"]);

    cy.wrap(response).then(() => {
      if (response.status === 200) {
        if (response.body.token_type === "totp") {
          expect(response.body, "totp_token").to.have.property("token").and.to
            .not.be.empty;

          const totpToken = response.body.token;
          if (!totpToken) {
            throw new Error("No token received from login");
          }
          globalState.set("totpToken", totpToken);
        }
      } else {
        throw new Error(
          `User login call failed to get totp token with status: "${response.status}" and message: "${response.body.error.message}"`
        );
      }
    });
  });
});
Cypress.Commands.add("terminate2Fa", (globalState) => {
  // Define the necessary variables and constant
  const baseUrl = globalState.get("baseUrl");
  const queryParams = `skip_two_factor_auth=true`;
  const apiKey = globalState.get("totpToken");
  const url = `${baseUrl}/user/2fa/terminate?${queryParams}`;

View on GitHub (pinned to 9b8b89dc37)

Solutions

  1. Print the full signin response body (cy.log(JSON.stringify(response.body))) to see what token was actually returned
  2. Verify the token_only=true query param is reaching the server and the signin endpoint version (/user/v2/signin) matches the server
  3. If the token field moved or was renamed, update both the chai expect and the read in commands.js

Example fix

// before
const totpToken = response.body.token;
if (!totpToken) throw new Error('No token received from login');
// after
const totpToken = response.body.token;
if (!totpToken)
  throw new Error(
    `No token received from login: ${JSON.stringify(response.body)}`
  );
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check the signin contract before relying on the token
const body = response.body;
if (body.token_type === 'totp') {
  expect(typeof body.token).to.equal('string');
  expect(body.token.length).to.be.greaterThan(0);
}

Type guard

const hasNonEmptyToken = (b) =>
  b != null && typeof b.token === 'string' && b.token.length > 0;

Try / catch

try {
  await cy.userLogin(globalState);
} catch (e) {
  if (/No token received from login/.test(e.message)) {
    // inspect full signin response; likely env/server issue, not test logic
    throw new Error(`signin returned empty token — check server logs`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Signin returns HTTP 200, token_type === 'totp', but body.token is '', null, or undefined — the preceding expect(...).to.not.be.empty normally raises a chai error before this line executes.

Common situations: Server bug returning 200 with an empty token; response shape change (token moved/nested); mocking/proxy stripping the token field in local environments.

Related errors


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