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` ); }}
Name | Type | Description |
---|---|---|
message | string | This is the message that will be displayed to the end users of the platform. |
details | 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");}
Name | Type | Description |
---|---|---|
message | string | This is the message that will be displayed to the end users of the platform. |
details | 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." );}
Name | Type | Description |
---|---|---|
message | string | This is the message that will be displayed to the end users of the platform. |
details | 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, } );}
Name | Type | Description |
---|---|---|
message | string | 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. |
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.
Name | Type | Description |
---|---|---|
externalErrorCode | string | This is the error code that is specific to the third party Ex: |
message | string | Any message that needs to be associated with this detail. |
externalHttpStatusCode | number | The http status code returned by the third parties request. |
externalContext | string | Any additional information that would be useful to log in the error. |
errorCode | string | An optional standarized error code associated with this detail. |