Error Handling

ShipEngine Connect applications can throw Errors just like any other JavaScript application. Any uncaught exception will terminate the currently executing method and generate an error log.

For example, the methods you implement will often need to perform input validation. If this validation fails, you can throw an error as in the example below.

for (let parcel of shipment.packages) {
if (parcel.packaging.code === "BOX" && parcel.weight.grams > 100000) {
throw new RangeError(`${parcel.packaging.name} cannot weigh more than 100 kilograms`);
}
}

Additional Error Properties

Before throwing an error, you can set additional properties that provide more context, enabling our platform to respond appropriately and provide meaningful feedback to users.

NameTypeDescription
codestring

A string that identifies the type of error. Most errors that occur in Node.js already have a code, but if you're throwing a new error, then we recommend that you use one of our pre-defined Error Codes below

statusCodenumber

The numeric status code associated with the error, if any. For errors that originate from an HTTP response, this should be the HTTP status code (e.g. 400, 404, 500)

externalErrorsstring[]

If the error is the result of calling an external service, then put any error messages that were returned by the service here.

externalWarningsstring[]

If the error is the result of calling an external service, then put any warning messages that were returned by the service here.

originalError

Error

The original error that occurred, if any. This is especially useful for debugging, since it will allow you to see the error message and stack trace where the problem occurred.

*any value

Any additional properties you add to the error will be logged, which is useful for debugging.

Error Codes

Most errors that occur in Node.js have a code property. When throwing your own errors, we encourage you to include a code as well. Using one of the following codes will help the ShipEngine Connect platform know how to handle your error appropriately.

NameDescription
ERR_INVALID

You should use this code to indicate a validation error. For example, your app may only allow certain values under specific conditions, or a field may be conditionally required.

ERR_UNAUTHORIZED

Use this code to indicate an authentication or authorization error. For example, if the transaction.session object is missing some required data or the session has expired.

ERR_EXTERNAL

You should use this code for any error that is the result of calling an external service, such as an API. This lets ShipEngine Connect know that the error came from a downstream service rather than directly in your app.

You should also set the statusCode property if possible to indicate the type of external error that occurred. For HTTP errors, you can use the HTTP status code (e.g. 400, 404, 500). For APIs that don't use HTTP status codes, we recomend using the most appropriate HTTP status code and also put the raw error/warning messages in externalErrors or externalWarnings.

ERR_APP_ERROR

This is a generic error code that simply indicates that the error was intentionally thrown by your app, as opposed to an unexpected error that occurred due to a bug or runtime exception.

Validation Error Example

This example demonstrates throwing a validation error with additional properties.

if (package.weight.grams > 100000) {
throw Object.assign(
new Error("Weight cannot exceed 100 kilograms"),
{
code: "ERR_INVALID",
actualWeight: package.weight.grams,
maxWeight: 100000,
}
);
}

External Error Example

This example rethrows an error from an external service, but first it adds additional properties.

try {
// Some code that makes an HTTP call
}
catch (error) {
error.code = "ERR_EXTERNAL";
error.statusCode = httpResponse.status;
error.externalErrors = [httpResponse.body.errorMessage];
error.headers = httpResponse.headers;
throw error;
}

Error Classes

In addition to JavaScript's built-in error classes, ShipEngine Connect includes several error classes you can use in your app. Each class corresponds to one of the error codes listed above and automatically sets the code property for you. You can also pass additional error properties to the constructor.

ValidationError

You should use this class for validation errors. For example, your app may only allow certain values under specific conditions, or a field may be conditionally required.

constructor(message | props)

The ValidationError constructor can accept a string (the error message) or an object containing additional error properties.

const { ValidationError } = require("@shipengine/connect");
// This only sets the `code` and `message` properties
throw new ValidationError("The package weight exceeds the maximum allowed");
// This sets the `code`, `message`, and additional properties
throw new ValidationError({
message: "The package weight exceeds the maximum allowed",
actualWeight: package.weight.ounces,
maxWeight: 2400,
});
import { ValidationError } from "@shipengine/connect";
// This only sets the `code` and `message` properties
throw new ValidationError("The package weight exceeds the maximum allowed");
// This sets the `code`, `message`, and additional properties
throw new ValidationError({
message: "The package weight exceeds the maximum allowed",
actualWeight: package.weight.ounces,
maxWeight: 2400,
});

UnauthorizedError

You should use this class to indicate an authentication or authorization error. For example, if the transaction.session object is missing some required data or the session has expired.

constructor(message | props)

The UnauthorizedError constructor can accept a string (the error message) or an object containing additional error properties.

const { UnauthorizedError } = require("@shipengine/connect");
// This only sets the `code` and `message` properties
throw new UnauthorizedError("Your session has expired");
// This sets the `code`, `message`, and additional properties
throw new UnauthorizedError({
message: "Your session has expired",
sessionID: session.id,
expiredAt: ession.expireDateTime,
});
import { UnauthorizedError } from "@shipengine/connect";
// This only sets the `code` and `message` properties
throw new UnauthorizedError("Your session has expired");
// This sets the `code`, `message`, and additional properties
throw new UnauthorizedError({
message: "Your session has expired",
sessionID: session.id,
expiredAt: ession.expireDateTime,
});

ExternalError

You should use this class when the error is the result of calling an external service, such as an API. This lets ShipEngine Connect know that the error came from a downstream service rather than directly in your app.

You should also set the statusCode property if possible to indicate the type of external error that occurred. For HTTP errors, you can use the HTTP status code (e.g. 400, 404, 500). For APIs that don't use HTTP status codes, we recomend using the most appropriate HTTP status code and also put the raw error/warning messages in externalErrors or externalWarnings.

constructor(message | props)

The ExternalError constructor can accept a string (the error message) or an object containing additional error properties.

const { ExternalError } = require("@shipengine/connect");
// This only sets the `code` and `message` properties
throw new ExternalError("The request exceeded the rate limit");
// This sets the `code`, `message`, and additional properties
throw new ExternalError({
message: "The request exceeded the rate limit",
statusCode: 429,
externalErrors: [httpResponse.body.errorMessage],
});
import { ExternalError } from "@shipengine/connect";
// This only sets the `code` and `message` properties
throw new ExternalError("The request exceeded the rate limit");
// This sets the `code`, `message`, and additional properties
throw new ExternalError({
message: "The request exceeded the rate limit",
statusCode: 429,
externalErrors: [httpResponse.body.errorMessage],
});

AppError

This is a generic error class that simply distinguishes errors that are intentionally thrown by your app, as opposed to an unexpected error that occurred due to a bug or runtime exception.

constructor(message | props)

The AppError constructor can accept a string (the error message) or an object containing additional error properties.

const { AppError } = require("@shipengine/connect");
// This only sets the `code` and `message` properties
throw new AppError("Unable to load app data");
// This sets the `code`, `message`, and additional properties
throw new AppError({
message: "Unable to load app data",
dataSource: "./app-data.xml",
});
import { AppError } from "@shipengine/connect";
// This only sets the `code` and `message` properties
throw new AppError("Unable to load app data");
// This sets the `code`, `message`, and additional properties
throw new AppError({
message: "Unable to load app data",
dataSource: "./app-data.xml",
});