Error Handling

All errors can be imported from the @shipengine/connect-runtime package and are thrown like normal JavaScript errors. These predefined errors are what we use to map to the appropriate http status codes in the response.

Warning

Avoid intentionally throwing generic JavaScript errors. These errors will be represented as an issue with your integration, and can cause your integration to be turned off from public consumption.

Copy
Copied
throw new Error('This is a bad idea'); // Don't do this.

Bad Request Error

A bad request error can be used to let consumers of your integration know that the request they sent your integration was either missing information, or was not a valid request. This lets the customer know what they can update to make a successful request in the future.

Copy
Copied
const { BadRequestError } = require('@shipengine/connect-runtime');
...
throw new BadRequestError('Destination zip code is a required property.');

You can also choose to throw an error with additional information for logging purposes.

Copy
Copied
const { BadRequestError, ErrorCode } = require('@shipengine/connect-runtime');
const { apiCall } = require('@example/api');
...
const result = apiCall(...);
const { status, message } = result.body;

if(status === 'bad-request') {
    const { errors } = result.body;
    const detailedErrors = errors.map(error => {
        return {
            externalErrorCode: error.CODE,
            message: error.WARNING,
            externalHttpStatusCode: result.statusCode,
            externalContext: error,
            errorCode: ErrorCode.ExternalClientError
        };
    })
    throw new BadRequestError(message, detailedErrors);
}

The definition for the BadRequestError is as follows

Copy
Copied
export interface ErrorDetail {
    /** The error code associated with the third parties system.
     * Useful for support to coordinate with third parties. */
    externalErrorCode?: string;
    /** The human readable message associated with this error */
    message?: string;
    /** The external http status code if applicable */
    externalHttpStatusCode?: number;
    /** Any object that might be useful in logs associated with this error */
    externalContext?: any;
    /** A standardized error code */
    errorCode?: ErrorCode;
}

export declare class BadRequestError extends BaseError {
    constructor(message: string, details?: ErrorDetail[] | ErrorDetail);
}

Unauthorized Error

An unauthorized error lets users know that their credentials have either expired or are incorrect. This can help our platform handle token refresh scenarios for oauth, as well as our support trouble shoot issues with customers credentials.

Copy
Copied
const { UnauthorizedError } = require('@shipengine/connect-runtime');
...
throw new UnauthorizedError('The access token provided has expired');

You can also choose to throw an error with additional information for logging purposes.

Copy
Copied
const { UnauthorizedError, ErrorCode } = require('@shipengine/connect-runtime');
const { apiCall } = require('@example/api');
...
const result = apiCall(...);
const { status, message } = result.body;

if(result.statusCode === 401) {
    const { errors } = result.body;
    const detailedErrors = errors.map(error => {
        return {
            externalErrorCode: error.CODE,
            message: error.WARNING,
            externalHttpStatusCode: result.statusCode,
            externalContext: error,
            errorCode: ErrorCode.ExternalClientError
        };
    })
    throw new UnauthorizedError(message, detailedErrors);
}

The definition for the UnauthorizedError is as follows

Copy
Copied
export interface ErrorDetail {
    /** The error code associated with the third parties system.
     * Useful for support to coordinate with third parties. */
    externalErrorCode?: string;
    /** The human readable message associated with this error */
    message?: string;
    /** The external http status code if applicable */
    externalHttpStatusCode?: number;
    /** Any object that might be useful in logs associated with this error */
    externalContext?: any;
    /** A standardized error code */
    errorCode?: ErrorCode;
}

export declare class UnauthorizedError extends BaseError {
    constructor(message: string, details?: ErrorDetail[] | ErrorDetail);
}

Rate Limit Error

A rate limit error lets our platform know that the external api is requesting that we slow down on making requests. This can often times be found in the form of an http status code 429 - Too Many Requests.

Copy
Copied
const { RateLimitError } = require('@shipengine/connect-runtime');
...
throw new RateLimitError('The third party requests you slow your roll.');

You can also choose to throw an error with additional details to help the platform determine when an appropriate time to start calling again would be.

Copy
Copied
const { RateLimitError } = require('@shipengine/connect-runtime');
const { apiCall } = require('@example/api');
...
const result = apiCall(...);
const { seconds_until_retry } = result.body;

if(result.statusCode === 429) {
    const { errors } = result.body;
    const rateLimitDetails = {
        retryAfterSeconds: seconds_until_retry,
        throttlingContext: result.body,
    }
    throw new RateLimitError(message, rateLimitDetails);

The definition for the RateLimitError is as follows

Copy
Copied
export interface RateLimitDetails {
    retryAfterSeconds?: number;
    retryAfterTime?: string;
    throttlingContext?: any;
}

export declare class RateLimitError extends BaseError {
    constructor(message: string, details?: RateLimitDetails);
}

External Server Error

An external server error lets consumers of your integration know that the third party is having a rough time. Their servers or networks might be experiencing issues, this should be thrown whenever the third party returns an http status code >= 500.

Copy
Copied
const { ExternalServerError } = require('@shipengine/connect-runtime');
...
throw new ExternalServerError('The third parties servers are unavailable.');

You can also choose to throw an error with additional details to help the platform determine when an appropriate time to start calling again would be.

Copy
Copied
const { ExternalServerError } = require('@shipengine/connect-runtime');
const { apiCall } = require('@example/api');
...
const result = apiCall(...);

if(result.statusCode >= 500) {
    throw new ExternalServerError('The third parties api is not accessible at the moment', {
        externalHttpStatusCode: result.statusCode,
        externalContext: result.body
    });

The definition for the ExternalServerError is as follows

Copy
Copied
export interface ErrorDetail {
    /** The error code associated with the third parties system.
     * Useful for support to coordinate with third parties. */
    externalErrorCode?: string;
    /** The human readable message associated with this error */
    message?: string;
    /** The external http status code if applicable */
    externalHttpStatusCode?: number;
    /** Any object that might be useful in logs associated with this error */
    externalContext?: any;
    /** A standardized error code */
    errorCode?: ErrorCode;
}

export declare class ExternalServerError extends BaseError {
    constructor(message: string, details?: ErrorDetail[] | ErrorDetail);
}