juspay/hyperswitch · error · Error
Payment Update Call Failed with error code "${response.body.
Error message
Payment Update Call Failed with error code "${response.body.error.code}" error message "${response.body.error.message}" What it means
Thrown by manualPaymentStatusUpdateTest when PUT {BASEURL}/payments/{paymentId}/manual-update (admin api-key + X-Merchant-Id) responds non-200. Note the command first asserts response.status equals the fixture's expectedStatus (default 200), then only the 200 path is success — any non-200 response reaches this throw, so a fixture that expects an error status still trips it unless the status assertion itself fails first.
Source
Thrown at cypress-tests/cypress/support/commands.js:8110
if (responseData.body && responseData.body.attempt_status) {
expect(response.body.attempt_status).to.equal(
responseData.body.attempt_status
);
}
if (responseData.body && responseData.body.error_code) {
expect(response.body.error_code).to.equal(
responseData.body.error_code
);
}
if (responseData.body && responseData.body.error_message) {
expect(response.body.error_message).to.equal(
responseData.body.error_message
);
}
} else {
throw new Error(
`Payment Update Call Failed with error code "${response.body.error.code}" error message "${response.body.error.message}"`
);
}
});
});
});
Cypress.Commands.add(
"manualPaymentUpdateNegativeTest",
(globalState, invalidAttemptId) => {
const merchantId = globalState.get("merchantId");
const paymentId = globalState.get("paymentID");
const completeUrl = `${Cypress.env("BASEURL")}/payments/${paymentId}/manual-update`;
const adminApiKey = globalState.get("adminApiKey");
const manualUpdateBody = {
merchant_id: merchantId,
attempt_id: invalidAttemptId,View on GitHub (pinned to 9b8b89dc37)
Solutions
- Verify globalState.get('adminApiKey') is set and valid for the environment
- Check the payment's actual attempt count and use the correct attempt_id (`${paymentId}_1` assumes exactly one attempt)
- Ensure the payment is in a state that accepts manual update (not already terminal)
- If a negative status is expected, compare expectedStatus before throwing so expected non-200s do not error
Example fix
// before (commands.js)
if (response.status === 200) { ... } else {
throw new Error(`Payment Update Call Failed ...`);
}
// after
if (response.status === 200) { ... } else if (expectedStatus !== response.status) {
throw new Error(`Payment Update Call Failed ...`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// preconditions before the manual update
expect(globalState.get('adminApiKey'), 'adminApiKey').to.not.be.empty;
expect(globalState.get('paymentID'), 'paymentID').to.not.be.empty;
// verify the attempt id actually exists before updating
cy.retrievePaymentCallTest({ globalState }).then(() => {
/* confirm attempt count before assuming `${paymentId}_1` */
}); Type guard
const isManualUpdateRejection = (status) => [400, 401, 403, 404].includes(status);
Try / catch
cy.manualPaymentStatusUpdateTest(globalState, data).catch?.((e) => {});
// or around the request in a wrapper:
cy.wrap(null)
.then(() => cy.manualPaymentStatusUpdateTest(globalState, data))
.catch((e) => {
const code = e.message.match(/error code "([^"]+)"/)?.[1];
if (code === 'IM_1' /* invalid attempt */) {
throw new Error('attempt_id does not match the payment — inspect attempts');
}
throw e;
}); Prevention
- Do not hardcode the '_1' attempt suffix — derive it from the payment's attempt count
- Ensure adminApiKey exists in globalState before any admin endpoint call
- Only run manual update on payments in non-terminal states
- Fix the commands.js else-branch so expected non-200 statuses do not throw
When it happens
Trigger: attempt_id `${paymentId}_1` does not match the payment's real attempt (e.g. second attempt is _2); adminApiKey invalid (401); merchant_id / X-Merchant-Id mismatch (403); payment already in a terminal state so manual update is rejected (400).
Common situations: Retries created multiple attempts so the hardcoded '_1' suffix is wrong; admin key not present in globalState for this environment; running the manual update twice; fixture declaring a non-200 expectedStatus that the else branch cannot represent.
Related errors
- Refund Manual Update Call Failed with error code "${response
- Invalid authentication type ${response.body.authentication_t
- Invalid capture method ${response.body.capture_method}
- Invalid authentication type: ${response.body.authentication_
- Retrieve Payment Call Failed with error code "${response.bod
AI-assisted analysis of juspay/hyperswitch@9b8b89dc37 (2026-08-16).
Data as JSON: /api/errors/44221ae92b5ced7b.
Report an issue: GitHub.