
Research
/Security News
9 Malicious NuGet Packages Deliver Time-Delayed Destructive Payloads
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.
@dotcom-reliability-kit/fetch-error-handler
Advanced tools
Properly handle fetch errors and avoid a lot of boilerplate in your app.
Properly handle fetch errors and avoid a lot of boilerplate in your app. This module is part of FT.com Reliability Kit.
Install @dotcom-reliability-kit/fetch-error-handler as a dependency:
npm install --save @dotcom-reliability-kit/fetch-error-handler
Include in your code:
import { handleFetchErrors } from '@dotcom-reliability-kit/fetch-error-handler';
// or
const { handleFetchErrors } = require('@dotcom-reliability-kit/fetch-error-handler');
You can use this function with any fetch call to throw appropriate errors based on the HTTP status code that you get back.
There are several ways to use it, as long as it is awaited and is called with either a Response object or a Promise that resolves to a Response.
Some of the options below result in more errors being caught, you can weigh this up when implementing in your own code.
In all of the APIs below, if the response ok property is false, i.e. when the status code is 400 or greater, then errors will be thrown.
[!WARNING] If you're using node-fetch then it's important to read the body of the request because of a known memory leak. If an error is thrown then we automatically drain the response body stream but, if the request is successful, you'll need to do this yourself.
This is the recommended API as this will allow you to handle the most errors (even DNS and timeout errors) correctly:
const response = await handleFetchErrors(
fetch('https://httpbin.org/status/500')
);
You must not await the fetch call itself if you want to handle DNS and timeout errors. This is safe to do and will not result in unhandled promise rejections – handleFetchErrors takes care of them all.
.thenThis API allows you to handle most errors based on the HTTP response, but it will not allow you to handle errors which occur before a valid response is returned, e.g. DNS or timeout errors.
const response = await fetch('https://httpbin.org/status/500').then(handleFetchErrors);
This API is for when you already have an HTTP response object, but it will not allow you to handle errors which occur before a valid response is returned, e.g. DNS or timeout errors.
const response = await fetch('https://httpbin.org/status/500');
await handleFetchErrors(response);
We throw different errors depending on the status code we get back from the fetch call.
If the URL you fetched responds with a status code in the range of 400–499 then this normally indicates that something is wrong with the current system. Maybe we're sending data in an invalid format or our API key is invalid. For this we throw a generic 500 error to indicate an issue with our system. It'll be an HTTPError. This error will have the following properties to help you debug:
error.statusCode // 500
error.code // FETCH_CLIENT_ERROR
error.data.upstreamUrl // The URL that was fetched
error.data.upstreamStatusCode // The status code that the URL responded with
error.data.responseBody // The body of the initial response
If the URL you fetched responds with a status code in the range of 500–599 then this indicates something is wrong with the upstream system. For this we can output an UpstreamServiceError and attribute it to the system we're fetching from. This error will have the following properties to help you debug:
error.statusCode // 502
error.code // FETCH_SERVER_ERROR
error.data.upstreamUrl // The URL that was fetched
error.data.upstreamStatusCode // The status code that the URL responded with
error.data.responseBody // The body of the initial response
If the hostname of the URL you fetched cannot be resolved, a DNS error will be thrown, it'll be an OperationalError. This error will have the following properties to help you debug:
error.code // FETCH_DNS_LOOKUP_ERROR
error.cause // The underlying DNS error that was caught
[!IMPORTANT]
This type of error will only be thrown if you use the "wrap the fetch function" API.
If the request times out or is aborted via AbortSignal, or the non-standard timeout option in node-fetch is used, then we throw an OperationalError. This error will have the following properties to help you debug:
error.code // FETCH_ABORT_ERROR or FETCH_TIMEOUT_ERROR
error.cause // The underlying abort or timeout error that was caught
[!IMPORTANT]
This type of error will only be thrown if you use the "wrap the fetch function" API.
If the connection is closed early by the server then we throw an UpstreamServiceError. This error will have the following properties to help you debug:
error.code // FETCH_SOCKET_HANGUP_ERROR
error.cause // The underlying socket error that was caught
[!IMPORTANT]
This type of error will only be thrown if you use the "wrap the fetch function" API.
If the URL you fetched responds with 200 status code and a JSON body, we try to parse that body to verify it is valid. If the body is invalid, we will throw an UpstreamServiceError with the error from the parsing, and the initial body of the response. This error will have the following properties to help you debug:
error.statusCode // 502
error.code // FETCH_INVALID_JSON_ERROR
error.data.upstreamUrl // The URL that was fetched
error.data.upstreamStatusCode // 200
error.data.upstreamErrorMessage // The error that was thrown when attempting to parse the body of the response
error.data.responseBody // The body of the initial response
[!IMPORTANT]
If the body is too long, we are truncating it because Splunk has a limit of characters to log.
If the URL you fetched responds with an ok property of false and a status code outside of the 400–599 range, then it's unclear what's happened but we reject with an error anyway to make sure we're able to debug. We output an HTTPError:
error.statusCode // 500
error.code // FETCH_UNKNOWN_ERROR
error.data.upstreamUrl // The URL that was fetched
error.data.upstreamStatusCode // The status code that the URL responded with
You can customise the thrown errors by creating your own fetch handler and passing in options.
Include in your code:
import { createFetchErrorHandler } from '@dotcom-reliability-kit/fetch-error-handler';
// or
const { createFetchErrorHandler } = require('@dotcom-reliability-kit/fetch-error-handler');
Create and use your own handler (the handler supports all the same usage methods as outlined here):
const handleFetchErrors = createFetchErrorHandler({
upstreamSystemCode: 'httpbin'
});
const response = await handleFetchErrors(fetch('https://httpbin.org/status/500'));
createFetchErrorHandler configuration optionsConfig options can be passed into the createFetchErrorHandler function to change the behaviour of the handler.
options.upstreamSystemCodeAttribute any fetch errors to a given Biz Ops system. This allows you to easily spot in your logs when an upstream system is the cause of an error. This must be a String and a valid system code.
const handleFetchErrors = createFetchErrorHandler({
upstreamSystemCode: 'next-navigation-api'
});
When this is set, any errors thrown by handleFetchErrors will have a relatesToSystems property which includes the given system code.
See the central contributing guide for Reliability Kit.
Licensed under the MIT license.
Copyright © 2023, The Financial Times Ltd.
FAQs
Properly handle fetch errors and avoid a lot of boilerplate in your app.
The npm package @dotcom-reliability-kit/fetch-error-handler receives a total of 0 weekly downloads. As such, @dotcom-reliability-kit/fetch-error-handler popularity was classified as not popular.
We found that @dotcom-reliability-kit/fetch-error-handler demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.