Error Reference
This page is a complete lookup for every error type you may encounter when integrating with AccruPay, including API-level errors, transaction outcomes, and provider decline reasons.
API errors
API errors appear in the GraphQL errors array. The response data is null or the failing field resolves to null.
{
"errors": [
{
"message": "Authentication error.",
"extensions": {
"code": "UNAUTHORIZED"
}
}
],
"data": null
}
Always check extensions.code — the message field is for human reading only and may change between releases.
extensions.code is either one of the fixed framework codes below, or a namespaced AppError key of the form @domain/REASON (e.g. @general/INTERNAL_SERVER_ERROR) for business-rule failures. Branch on the code; treat any @…/… key as a business error and read message for detail.
| Code | Cause | Fix |
|---|---|---|
UNAUTHORIZED | The accrupay-api-secret header is missing, malformed, or the secret has been rotated | Verify the API secret value in your environment; ensure the header name is lowercase accrupay-api-secret |
FORBIDDEN | The credentials are valid but the authenticated merchant is not permitted to access the requested resource | Confirm the API key belongs to the correct merchant account; check that the resource was created by this merchant |
GRAPHQL_VALIDATION_FAILED | A required argument is missing or a value fails type/format validation | Check the message for field-level detail; correct the input and retry |
GRAPHQL_PARSE_FAILED | The GraphQL document is malformed | Fix the query syntax |
@domain/REASON (AppError key) | A business rule was violated (e.g. resource not found, duplicate merchantInternalTransactionCode, provider selection failure) | The key identifies the specific reason; read message and correct the request |
INTERNAL_SERVER_ERROR | Unexpected server-side failure not caused by the input | Retry with exponential backoff; if it persists, open a support ticket with the full error response body |
Transaction errors
Transaction declines and failures are not GraphQL errors. The mutation resolves with HTTP 200 and a successful GraphQL response. The failure is indicated by transaction.status in the response data.
{
"data": {
"merchantApiServerPaymentMethodTransactionCreate": {
"id": "txn-uuid",
"status": "DECLINED",
"providerError": "Do not honor"
}
}
}
| Status | Cause | What to show the customer |
|---|---|---|
DECLINED | The card network or issuer rejected the charge (e.g. insufficient funds, card blocked, card expired) | "Your payment was declined. Please try a different payment method." |
FAILED | A processing failure prevented the transaction from being submitted (e.g. invalid card data, provider timeout, configuration error) | "Something went wrong processing your payment. Please try again or contact support." |
Neither status is retryable with the same payment method without customer action. For DECLINED, prompt the customer to re-enter payment details or use a different card. For FAILED, a retry may succeed if the cause was transient (e.g. a provider timeout), but you must use a new merchantInternalTransactionCode — a code from a failed attempt is permanently consumed. See Idempotency for the exact rule.
providerError field
Most transaction return types include a providerError field. It is populated when status is DECLINED or FAILED.
{
id
status
providerError
}
providerError contains the raw reason string from the provider (e.g. "Insufficient funds", "Do not honor", "Invalid card number", "Expired card").
How to use providerError
| Use | Recommendation |
|---|---|
| Internal logging | Log the full providerError value for every non-approved transaction |
| Support tickets | Include providerError in support context to help diagnose declines |
| Customer-facing messages | Do not show providerError directly; map to a user-friendly message |
| Retry logic | Use providerError to distinguish hard declines (do not retry) from soft declines (may retry) |
Common hard decline indicators in providerError: "Do not honor", "Stolen card", "Lost card", "Restricted card". These should not be retried.
Common soft decline indicators: "Insufficient funds", "Exceeds withdrawal limit". These may succeed after the customer resolves the underlying issue.
Network and transport errors
HTTP-level failures do not produce a GraphQL response body. Handle these separately from GraphQL errors.
| Scenario | Behavior | Recommendation |
|---|---|---|
HTTP 200, errors[] present | GraphQL error | Branch on extensions.code |
HTTP 200, data present | Success | Check transaction.status |
| HTTP 401 | Request rejected before reaching GraphQL | Check the accrupay-api-secret header |
| HTTP 5xx | Server error before GraphQL processing | Retry with backoff |
| Timeout / no response | Transport failure | Query by merchantInternalTransactionCode before retrying to avoid duplicate charges |
SDK error handling
The @accrupay/node SDK does not throw typed error classes. It surfaces errors through callbacks you pass to the constructor:
| Callback | Fires on |
|---|---|
onAuthError() | Authentication failures (UNAUTHORIZED) — receives no argument |
onGraphQLError(errors) | A populated GraphQL errors[] — receives ReadonlyArray<GraphQLFormattedError> |
onNetworkError(error) | Transport-level failures (timeout, DNS, connection refused) — receives an Error |
Inspect extensions.code on each entry in onGraphQLError to branch on the codes above. See Node SDK — Error handling.
Related
- API Errors — GraphQL error envelope detail and transaction status vs API errors
- GraphQL Overview
- Reconciliation — using
providerErrorfor statement matching