Skip to content

Commit

Permalink
Add cause property with the original error to RequestError (#2327)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
katsanva and sindresorhus committed Feb 3, 2024
1 parent f10e151 commit 4cbd01d
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 6 deletions.
11 changes: 6 additions & 5 deletions documentation/8-errors.md
Expand Up @@ -19,8 +19,9 @@ All Got errors contain various metadata, such as:

Read the article [here](async-stack-traces.md).

**Note:**
> [!NOTE]
> - The error codes may differ when the root error has a `code` property set.
> - The root error will be propagated as is via the [`cause`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) property.
### `RequestError`

Expand Down Expand Up @@ -62,8 +63,8 @@ A request is successful when the status code of the final request is `2xx` or `3

When [following redirects](2-options.md#followredirect), a request is successful **only** when the status code of the final request is `2xx`.

**Note:**
> - `304` responses are always considered successful.
> [!NOTE]
> `304` responses are always considered successful.
### `MaxRedirectsError`

Expand All @@ -73,8 +74,8 @@ When the server redirects you more than ten times. Includes a `response` propert

### `UnsupportedProtocolError`

**Note:**
> - This error is not public.
> [!NOTE]
> This error is not public.
**Code: `ERR_UNSUPPORTED_PROTOCOL`**

Expand Down
2 changes: 1 addition & 1 deletion source/core/errors.ts
Expand Up @@ -27,7 +27,7 @@ export class RequestError<T = unknown> extends Error {
readonly timings?: Timings;

constructor(message: string, error: Partial<Error & {code?: string}>, self: Request | Options) {
super(message);
super(message, {cause: error});
Error.captureStackTrace(this, this.constructor);

this.name = 'RequestError';
Expand Down
23 changes: 23 additions & 0 deletions test/error.ts
Expand Up @@ -4,6 +4,7 @@ import net from 'node:net';
import http from 'node:http';
import stream from 'node:stream';
import {pipeline as streamPipeline} from 'node:stream/promises';
import {Agent} from 'node:https';
import test from 'ava';
import getStream from 'get-stream';
import is from '@sindresorhus/is';
Expand Down Expand Up @@ -359,6 +360,28 @@ test.skip('the old stacktrace is recovered', async t => {
t.not(error?.stack!.indexOf('at get'), error?.stack!.lastIndexOf('at get'));
});

test('should wrap got cause', async t => {
const error = await t.throwsAsync<RequestError>(got('https://github.com', {retry: {limit: 0}, timeout: {request: 1}}));
const cause = error?.cause as TimeoutError;
t.is(error?.code, cause.code);
t.is(error?.message, cause.message);
});

test('should wrap non-got cause', async t => {
class SocksProxyAgent extends Agent {
createConnection() {
throw new SocksClientError('oh no');
}
}
class SocksClientError extends Error {}
const error = await t.throwsAsync<RequestError>(got('https://github.com', {retry: {limit: 0}, timeout: {read: 1}, agent: {https: new SocksProxyAgent()}}));
const cause = error?.cause as Error;
t.is(error?.code, 'ERR_GOT_REQUEST_ERROR');
t.is(error?.message, cause.message);
t.is(error?.message, 'oh no');
t.assert(cause instanceof SocksClientError);
});

test.serial('custom stack trace', withServer, async (t, _server, got) => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const ErrorCaptureStackTrace = Error.captureStackTrace;
Expand Down

0 comments on commit 4cbd01d

Please sign in to comment.