{"record":{"id":"78ecca7dc3a72136","repo":"juspay/hyperswitch","slug":"refund-manual-update-call-failed-with-error-code","errorCode":null,"errorMessage":"Refund Manual Update Call Failed with error code \"${response.body?.error?.code}\" error message \"${response.body?.error?.message}\"","messagePattern":"Refund Manual Update Call Failed with error code \"(.+?)\" error message \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cypress-tests/cypress/support/commands.js","lineNumber":8176,"sourceCode":"      url: completeUrl,\n      headers: {\n        \"Content-Type\": \"application/json\",\n        \"api-key\": adminApiKey,\n        \"X-Merchant-Id\": merchantId,\n      },\n      body: {\n        merchant_id: merchantId,\n        ...refundManualUpdateRequestBody.Request,\n      },\n      failOnStatusCode: false,\n    }).then((response) => {\n      logRequestId(response.headers[\"x-request-id\"]);\n\n      cy.wrap(response).then(() => {\n        if (response.status === 200) {\n          expect(response.status).to.eq(200);\n        } else {\n          throw new Error(\n            `Refund Manual Update Call Failed with error code \"${response.body?.error?.code}\" error message \"${response.body?.error?.message}\"`\n          );\n        }\n      });\n    });\n  }\n);\n\nCypress.Commands.add(\n  \"IncomingWebhookTest\",\n  (globalState, webhookBody, webhookConfig, webhookType = \"payment\") => {\n    const connector = globalState.get(\"connectorId\");\n    const merchantId = globalState.get(\"merchantId\");\n    const completeUrl = `${Cypress.env(\"BASEURL\")}/webhooks/${merchantId}/${connector}`;\n\n    // Resolve the reference ID based on webhook type\n    const webhookTypeMap = {\n      payment: {","sourceCodeStart":8158,"sourceCodeEnd":8194,"githubUrl":"https://github.com/juspay/hyperswitch/blob/9b8b89dc378b62c9a6feda647bad4719d2de7699/cypress-tests/cypress/support/commands.js#L8158-L8194","documentation":"Thrown by manualRefundStatusUpdateTest when PUT {BASEURL}/refunds/{refundId}/manual-update (admin api-key + X-Merchant-Id) responds non-200. The command treats 200 as the only success path; the interpolated error code/message use optional chaining, so missing error bodies render as the string 'undefined'.","triggerScenarios":"refundId absent from globalState (URL becomes /refunds/undefined/manual-update → 404); adminApiKey invalid (401); refund already in a terminal state so the transition is rejected (400); merchant_id in the body not matching the refund's merchant (403).","commonSituations":"Spec calls the manual refund update before a refund was created; refund create step failed silently so refundId was never set; running the update twice against a refund that already reached a terminal status.","solutions":["Ensure the refund-create step ran and set globalState refundId before this command","Verify adminApiKey and X-Merchant-Id match the refund's merchant","Retrieve the refund (GET /refunds/{id}) and confirm its status still permits manual update","Check x-request-id in server logs when the error body is unclear"],"exampleFix":"// before\ncy.manualRefundStatusUpdateTest(globalState, body);\n// after\nif (!globalState.get('refundId'))\n  throw new Error('refundId missing - create the refund first');\ncy.manualRefundStatusUpdateTest(globalState, body);","handlingStrategy":"validation","validationCode":"// preconditions for the refund manual update\nif (!globalState.get('refundId')) {\n  throw new Error('refundId missing — create the refund first');\n}\nexpect(globalState.get('adminApiKey'), 'adminApiKey').to.not.be.empty;\nexpect(globalState.get('merchantId'), 'merchantId').to.not.be.empty;\ncy.manualRefundStatusUpdateTest(globalState, requestBody);","typeGuard":null,"tryCatchPattern":"cy.wrap(null)\n  .then(() => cy.manualRefundStatusUpdateTest(globalState, body))\n  .catch((e) => {\n    if (/Refund Manual Update Call Failed/.test(e.message)) {\n      // inspect the refund state before retrying blindly\n      cy.retrieveRefundCallTest(globalState);\n    }\n    throw e;\n  });","preventionTips":["Create the refund in the same spec before any manual refund update","Run manual updates once per refund — terminal-state refunds reject transitions","Keep adminApiKey and X-Merchant-Id consistent with the refund's merchant","Check refund status via GET /refunds/{id} when an update is unexpectedly rejected"],"tags":["cypress","manual-update","refunds","admin-api","precondition"],"backgroundTag":null,"analyzedSha":"9b8b89dc378b62c9a6feda647bad4719d2de7699","analyzedAt":"2026-08-16T09:01:53.433Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}