juspay/hyperswitch · error · Error

Refund Manual Update Call Failed with error code "${response

Error message

Refund Manual Update Call Failed with error code "${response.body?.error?.code}" error message "${response.body?.error?.message}"

What it means

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'.

Source

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

      url: completeUrl,
      headers: {
        "Content-Type": "application/json",
        "api-key": adminApiKey,
        "X-Merchant-Id": merchantId,
      },
      body: {
        merchant_id: merchantId,
        ...refundManualUpdateRequestBody.Request,
      },
      failOnStatusCode: false,
    }).then((response) => {
      logRequestId(response.headers["x-request-id"]);

      cy.wrap(response).then(() => {
        if (response.status === 200) {
          expect(response.status).to.eq(200);
        } else {
          throw new Error(
            `Refund Manual Update Call Failed with error code "${response.body?.error?.code}" error message "${response.body?.error?.message}"`
          );
        }
      });
    });
  }
);

Cypress.Commands.add(
  "IncomingWebhookTest",
  (globalState, webhookBody, webhookConfig, webhookType = "payment") => {
    const connector = globalState.get("connectorId");
    const merchantId = globalState.get("merchantId");
    const completeUrl = `${Cypress.env("BASEURL")}/webhooks/${merchantId}/${connector}`;

    // Resolve the reference ID based on webhook type
    const webhookTypeMap = {
      payment: {

View on GitHub (pinned to 9b8b89dc37)

Solutions

  1. Ensure the refund-create step ran and set globalState refundId before this command
  2. Verify adminApiKey and X-Merchant-Id match the refund's merchant
  3. Retrieve the refund (GET /refunds/{id}) and confirm its status still permits manual update
  4. Check x-request-id in server logs when the error body is unclear

Example fix

// before
cy.manualRefundStatusUpdateTest(globalState, body);
// after
if (!globalState.get('refundId'))
  throw new Error('refundId missing - create the refund first');
cy.manualRefundStatusUpdateTest(globalState, body);
Defensive patterns

Strategy: validation

Validate before calling

// preconditions for the refund manual update
if (!globalState.get('refundId')) {
  throw new Error('refundId missing — create the refund first');
}
expect(globalState.get('adminApiKey'), 'adminApiKey').to.not.be.empty;
expect(globalState.get('merchantId'), 'merchantId').to.not.be.empty;
cy.manualRefundStatusUpdateTest(globalState, requestBody);

Try / catch

cy.wrap(null)
  .then(() => cy.manualRefundStatusUpdateTest(globalState, body))
  .catch((e) => {
    if (/Refund Manual Update Call Failed/.test(e.message)) {
      // inspect the refund state before retrying blindly
      cy.retrieveRefundCallTest(globalState);
    }
    throw e;
  });

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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