Error Handling

ShipEngine Connect applications use error objects defined in the @shipengine/connect-runtime package to determine when an error was thrown intentionally by the implementor.

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.

Bad Request Error

This type of error means that the user has submitted some information in their request that is causing the function to fail. This allows the user to know that if they change something about their request it could be successful.

import { BadRequestError } from "@shipengine/connect-runtime";
// ...
for (let package of request.packages) {
if (
package.package_code === "BOX" &&
package.weight_details.weight_in_grams > 100000
) {
throw new BadRequestError(
`${package.package_code} cannot weigh more than 100 kilograms`
);
}
}
NameTypeDescription
messagestring

This is the message that will be displayed to the end users of the platform.

details

ErrorDetail | ErrorDetail[]

This contains additional information that needs to be logged along side the error.

Unauthorized Error

This error lets a user know that they need to update their credentials in order to continue using their connection.

import { UnauthorizedError } from "@shipengine/connect-runtime";
// ...
const response = await apiCall(THIRD_PARTY_API_URL, { credentials });
if (response.statusCode === 401) {
throw new UnauthorizedError("Invalid Credentials");
}
NameTypeDescription
messagestring

This is the message that will be displayed to the end users of the platform.

details

ErrorDetail | ErrorDetail[]

This contains additional information that needs to be logged along side the error.

External Server Error

This type of error lets the user know that there is an issue with the outside world that we cannot resolve.

import { ExternalServerError } from "@shipengine/connect-runtime";
// ...
const response = await apiCall(THIRD_PARTY_API_URL, { credentials });
if (response.statusCode > 500) {
throw new ExternalServerError(
"There was an issue with the third parties api."
);
}
NameTypeDescription
messagestring

This is the message that will be displayed to the end users of the platform.

details

ErrorDetail | ErrorDetail[]

This contains additional information that needs to be logged along side the error.

Rate Limit Error

This lets the platform know that it should hold off on making more calls due to Rate Limiting by the third party.

import { RateLimitError } from "@shipengine/connect-runtime";
// ...
const response = await apiCall(THIRD_PARTY_API_URL, { credentials });
if (response.statusCode === 429) {
throw new RateLimitError(
"Too many requests were made to the third parties apis.",
{
retryAfterSeconds: response.body.retry_after,
throttlingContext: response.body,
}
);
}
NameTypeDescription
messagestring

This is the message that will be displayed to the end users of the platform.

details

object

This contains additional information related to a rate limiting error.

details.retryAfterSeconds

number

The number of seconds the platform should wait before making another request.

details.retryAfterTime

string

The time the platform should wait for until it makes it's next request.ISO-8601

details.throttlingContext

any

Any additional information that could be beneficial to see in the logs. (Could be the full body of the response)

Error Detail

Along with the base error message that can be set when throwing a new error, you also have the option of passing in additional properties through an ErrorDetail object or Array of ErrorDetail objects. Lets take a look at the previous example of throwing a bad request error, but lets add some more detailed information for logging purposes.

import { BadRequestError } from "@shipengine/connect-runtime";
// ...
const response = await apiCall(THIRD_PARTY_API_URL, { credentials });
if (response.statusCode === 400) {
throw new BadRequestError("There was an issue with the third parties api.", {
externalErrorCode: response.body.custom_third_party_error_code,
message: response.body.custom_error_message,
externalHttpStatusCode: 400,
externalContext: response.body,
errorCode: StandardizedErrorCode.ExternalClientError,
});
}

Now when we see logs this new information will appear alongside the original error message, but will not be displayed to the end users.

NameTypeDescription
externalErrorCodestring

This is the error code that is specific to the third party Ex: AMAZ_2324, SHOP_3435. This can be useful for our support to help diagnose issues.

messagestring

Any message that needs to be associated with this detail.

externalHttpStatusCodenumber

The http status code returned by the third parties request.

externalContextstring

Any additional information that would be useful to log in the error.

errorCodestring

An optional standarized error code associated with this detail. Generic, Validation, Unauthorized, ExternalServerError, ExternalClientError