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
- 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
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
- 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
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
- Payment Update Call Failed with error code "${response.body.
- No user info token available
- Eligibility check failed with status: ${response.status} and
- Unsupported connector: ${connectorId}
- Unsupported payment method type: ${payment_method_type}
AI-assisted analysis of juspay/hyperswitch@9b8b89dc37 (2026-08-16).
Data as JSON: /api/errors/78ecca7dc3a72136.
Report an issue: GitHub.