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.
Name | Type | Description |
---|---|---|
code | string | 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 |
statusCode | number | 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) |
externalErrors | string[] | If the error is the result of calling an external service, then put any error messages that were returned by the service here. |
externalWarnings | string[] | If the error is the result of calling an external service, then put any warning messages that were returned by the service here. |
originalError | 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.
Name | Description |
---|---|
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 |
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 |
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` propertiesthrow new ValidationError("The package weight exceeds the maximum allowed");// This sets the `code`, `message`, and additional propertiesthrow 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` propertiesthrow new ValidationError("The package weight exceeds the maximum allowed");// This sets the `code`, `message`, and additional propertiesthrow 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` propertiesthrow new UnauthorizedError("Your session has expired");// This sets the `code`, `message`, and additional propertiesthrow 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` propertiesthrow new UnauthorizedError("Your session has expired");// This sets the `code`, `message`, and additional propertiesthrow 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` propertiesthrow new ExternalError("The request exceeded the rate limit");// This sets the `code`, `message`, and additional propertiesthrow 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` propertiesthrow new ExternalError("The request exceeded the rate limit");// This sets the `code`, `message`, and additional propertiesthrow 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` propertiesthrow new AppError("Unable to load app data");// This sets the `code`, `message`, and additional propertiesthrow new AppError({ message: "Unable to load app data", dataSource: "./app-data.xml",});
import { AppError } from "@shipengine/connect";// This only sets the `code` and `message` propertiesthrow new AppError("Unable to load app data");// This sets the `code`, `message`, and additional propertiesthrow new AppError({ message: "Unable to load app data", dataSource: "./app-data.xml",});