{"record":{"id":"c28e7787b5956197","repo":"juspay/hyperswitch","slug":"health-check-failed-with-status-response-statu","errorCode":null,"errorMessage":"Health Check failed with status: `${response.status}` and body: `${response.body}`","messagePattern":"Health Check failed with status: `(.+?)` and body: `(.+?)`","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cypress-tests/cypress/support/commands.js","lineNumber":602,"sourceCode":"\nCypress.Commands.add(\"healthCheck\", (globalState) => {\n  const baseUrl = globalState.get(\"baseUrl\");\n  const url = `${baseUrl}/health`;\n\n  cy.request({\n    method: \"GET\",\n    url: url,\n    headers: {\n      Accept: \"application/json\",\n    },\n  }).then((response) => {\n    logRequestId(response.headers[\"x-request-id\"]);\n\n    cy.wrap(response).then(() => {\n      if (response.status === 200) {\n        expect(response.body).to.equal(\"health is good\");\n      } else {\n        throw new Error(\n          `Health Check failed with status: \\`${response.status}\\` and body: \\`${response.body}\\``\n        );\n      }\n    });\n  });\n});\n\n/**\n * Creates a merchant account and optionally validates response fields.\n * @param {Object} merchantCreateBody - The merchant creation request body\n * @param {Object} globalState - The global state object\n * @param {Object} options - Options for merchant creation\n * @param {string|null} [options.expectedMerchantAccountType=null] - Expected merchant_account_type to validate (optional)\n * @param {string} [options.expectedProductType=\"orchestration\"] - Expected product_type to validate. Pass a string value like \"vault\", \"recon\", \"recovery\", etc. to validate the response contains this product_type. Defaults to \"orchestration\".\n * @param {number} [options.expectedStatus=200] - Expected HTTP status code. Use 400 for negative test cases.\n * @param {string} [options.expectedErrorCode=null] - Expected error code in response body (for negative test cases, e.g. \"IR_06\")\n * @param {string} [options.merchantIdStateKey=\"merchantId\"] - Key to store merchant ID in global state\n * @param {string} [options.profileIdStateKey=\"profileId\"] - Key to store profile ID in global state","sourceCodeStart":584,"sourceCodeEnd":620,"githubUrl":"https://github.com/juspay/hyperswitch/blob/9b8b89dc378b62c9a6feda647bad4719d2de7699/cypress-tests/cypress/support/commands.js#L584-L620","documentation":"Thrown by the healthCheck Cypress command in cypress-tests/cypress/support/commands.js: it GETs the router's health endpoint (Accept: application/json) and, unless status is 200 with body exactly 'health is good', throws with the actual status and body. It is the readiness probe tests call before touching the environment under test.","triggerScenarios":"healthCheck runs while the router service is still starting, crashed, or misconfigured (DB/migrations pending) so /health returns 5xx; or the baseUrl in globalState points at the wrong host/port so the response is a proxy/gateway error page (status 404/502 with an HTML body).","commonSituations":"CI pipeline starts Cypress before the service is up (no readiness gate); local run against a stopped container; port mismatch after a compose change; k8s liveness not yet passing during rollout; smoke tests against an environment mid-deploy.","solutions":["Confirm the target service is up: curl <baseUrl>/health manually and expect 200 'health is good'","Fix the baseUrl/port in globalState if it points at the wrong place (the body in the message usually reveals a proxy error page)","In CI, add a readiness wait before invoking Cypress so healthCheck is a verification, not the first probe","Check service logs for startup failures (DB unreachable, pending migrations) if health keeps failing"],"exampleFix":"// before\ncy.healthCheck(url); // one-shot, throws while service boots\n\n// after (retry until ready)\nCypress.Commands.add('healthCheckWithRetry', (url, attempts = 10) => {\n  const attempt = (n) =>\n    cy.request({ method: 'GET', url, failOnStatusCode: false }).then((response) => {\n      if (response.status === 200 && response.body === 'health is good') return;\n      if (n <= 1) {\n        throw new Error(`Health Check failed with status: ${response.status} and body: ${response.body}`);\n      }\n      cy.wait(3000).then(() => attempt(n - 1));\n    });\n  return attempt(attempts);\n});","handlingStrategy":"retry","validationCode":"// Probe readiness before the assertion-style healthCheck\ncy.request({ method: 'GET', url: `${baseUrl}/health`, failOnStatusCode: false }).then((response) => {\n  if (response.status !== 200) {\n    throw new Error(`Service not ready (${response.status}); wait for deployment to finish before running tests`);\n  }\n});","typeGuard":null,"tryCatchPattern":"// Readiness-style retry around the strict one-shot check\nCypress.Commands.add('healthCheckWithRetry', (url, attempts = 10) => {\n  const attempt = (n) =>\n    cy.request({ method: 'GET', url, failOnStatusCode: false }).then((response) => {\n      if (response.status === 200 && response.body === 'health is good') return;\n      if (n <= 1) {\n        throw new Error(`Health Check failed with status: \\`${response.status}\\` and body: \\`${response.body}\\``);\n      }\n      cy.wait(3000).then(() => attempt(n - 1));\n    });\n  return attempt(attempts);\n});","preventionTips":["Add a CI readiness gate (curl /health loop) before Cypress starts","Verify baseUrl/host/port in globalState when the failing body looks like a gateway page","Expect exactly the body 'health is good' — a 200 with different body is still a failure"],"tags":["cypress","health-check","readiness","network","ci"],"backgroundTag":null,"analyzedSha":"9b8b89dc378b62c9a6feda647bad4719d2de7699","analyzedAt":"2026-08-16T09:01:53.433Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}