Skip to main content

Reactor Errors

Errors that occur when invoking a reactor will be formatted according to the standard Basis Theory Error Response. The contents of each error will vary based on the failure scenario, and there are several standard error codes that are possible that can be used to determine the cause of the error.

Reactor Error Codes

CodeMeaningCommon Scenarios
400Bad Request
  • Missing or invalid args on the request
  • Invalid Reactor Configuration
401Authentication Error
  • Invalid or unknown credentials
  • Credentials are valid, but lack permission to complete the operation
402Invalid Payment Method
  • Expired Card
  • A test card or bank account was used in a production environment, or vice-versa
  • An external API denied the card or bank account
422Unprocessable Entity
  • Reactor code is not a valid function
429Rate Limit Error
  • An external API responded with a 429 HTTP response code
500Reactor Runtime Error
  • An unhandled exception occurred
  • An external API responded with a 5XX HTTP response code
  • External API connection failure

There are a few different root causes for why one of these errors may be returned from a reactor:

  1. An error occurred within Basis Theory's reactor execution framework when processing your request. For example, this can occur if the reactor code is invalid and fails to compile (JavaScript code is validated before being executed) resulting in a 422 error, or if the provided args contain an invalid expression resulting in a 400 error.

  2. An error occurred within your reactor code. For example, an HTTP call is made to an external API and they responded with an error, or a runtime error occurred within the code due to a bug. The following section details best practices when handling errors within reactor code.

Handling Errors in Reactor Code

The @basis-theory/basistheory-reactor-formulas-sdk-js npm package can be referenced within your reactor code to better control the status codes and messages included on reactor errors.

Error Types

This package includes several error types that can be thrown from your code, including:

TypeStatus CodeDetail
AuthenticationError401Authentication Failed
AuthorizationError403Forbidden
BadRequestError400Bad Request
InvalidPaymentMethodError402Invalid Payment Method
RateLimitError429Rate Limit Exceeded
ReactorRuntimeError500Reactor Runtime Error
ServiceUnavailableError503Service Unavailable Error
CustomHttpResponseErroranyN/A

If your reactor code throws any of these standard error types, with the exception of CustomHttpResponseError, they will be caught and translated into a standard Basis Theory error response with the corresponding status code and detail specified in the table above.

If a CustomHttpResponseError is thrown from a reactor, the status code, headers, and body defined by the error will be used to construct a custom API response.

Any other errors raised from reactor code will result in a ReactorRuntimeError containing the original error object and the response will have status code 500.

Error Constructors

Each of the error types, excluding CustomHttpResponseError, accepts a constructor argument that will be returned within the errors block. The constructor argument for each type supports several error formats, for example:


// Throwing an error constructed with a string error message:
const { ReactorRuntimeError } = require('@basis-theory/basis-theory-reactor-formulas-sdk-js');
throw new ReactorRuntimeError('My error message');

// Would result in the following error response:
{
"status": 500,
"detail": "Reactor Runtime Error",
"errors": {
"error": ["My error message"]
}
}

Custom Errors

To have complete control over the response body that is returned, including custom status codes, custom headers, or to have complete control over the response body, a CustomHttpResponseError can be thrown from a reactor.

For example, throwing the following error:

const { CustomHttpResponseError } = require('@basis-theory/basis-theory-reactor-formulas-sdk-js');
throw new CustomHttpResponseError({
status: 400,
headers: {
"Custom-Response-Header-1": "custom-value-1",
"Custom-Response-Header-2": "custom-value-2"
},
body: {
"custom_property": "value",
"custom_object": {
"custom_nested_property": "value"
}
}
});

results in an API response with status code 400 having the headers:

Custom-Response-Header-1: custom-value-1
Custom-Response-Header-2: custom-value-2

and the response body:

{
"custom_property": "value",
"custom_object": {
"custom_nested_property": "value"
}
}

Best Practices

When integrating with an external API within a reactor, we strongly recommend handling all vendor-specific errors and translating into an appropriate Basis Theory error type.

Some external APIs express error scenarios via HTTP status codes, while others opt to return a generic status code such as 200 OK while expressing the error condition within the response body. Each API is unique and error handling may also look very different when using an SDK vs making a direct HTTP call with a generic HTTP client. For these reasons, error handling logic needs to be customized for each external API call made from within your reactor code.

In order to make it easier to debug errors returned by a reactor, we strongly encourage you to handle all potential errors and to craft your reactor responses such that you have sufficient information available in your system to react appropriately to each error scenario.

Examples

module.exports = async function (req) {
const stripe = require('stripe')(req.configuration.STRIPE_PRIVATE_API_KEY);
const {
AuthenticationError,
BadRequestError,
InvalidPaymentMethodError,
RateLimitError,
ReactorRuntimeError,
} = require('@basis-theory/basis-theory-reactor-formulas-sdk-js');

try {
const token = await stripe.tokens.create({
// redacted for simplicity
});

return {
raw: token,
};
} catch (err) {
// the stripe sdk throws an error containing a type value
// here we translate from stripe-specific error types into Basis Theory errors
switch (err.type) {
case 'StripeCardError':
throw new InvalidPaymentMethodError();
case 'StripeRateLimitError':
throw new RateLimitError();
case 'StripeAuthenticationError':
throw new AuthenticationError();
case 'StripeInvalidRequestError':
throw new BadRequestError();
default:
throw new ReactorRuntimeError(err);
}
}
};