Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unhandled 'error' event when using AbortSignal to cancel requests #1801

Open
AleCaste opened this issue Jan 23, 2024 · 2 comments
Open

Unhandled 'error' event when using AbortSignal to cancel requests #1801

AleCaste opened this issue Jan 23, 2024 · 2 comments
Labels

Comments

@AleCaste
Copy link

Reproduction

Steps to reproduce the behavior:

const controller = new AbortController();

const fetchTimeout = setTimeout(() => {
    controller.abort();
}, 500);   // Try different values from 0 - 3000

const requestOptions = {
    method: 'POST',
    headers: {
      'content-type': 'application/json'
    },
    body: JSON.stringify({test: 'test'}),
    signal: controller.signal
};

try {
  const response = await fetch(url, requestOptions)
} catch (err) {
  // handle error
}

The problem is somehow intermittent. Try different timeout values until you can reproduce it.
I get the following error:

node:events:368
      throw er; // Unhandled 'error' event
      ^

AbortError: The operation was aborted.
    at abort (file:///D:/xampp/htdocs/fetch_retry_test/node_modules/node-fetch/src/index.js:70:18)
    at file:///D:/xampp/htdocs/fetch_retry_test/node_modules/node-fetch/src/index.js:87:4
    at new Promise (<anonymous>)
    at fetch (file:///D:/xampp/htdocs/fetch_retry_test/node_modules/node-fetch/src/index.js:49:9)
    at wrappedFetch (D:\xampp\htdocs\fetch_retry_test\node_modules\fetch-retry\index.js:71:9)
    at Timeout._onTimeout (D:\xampp\htdocs\fetch_retry_test\node_modules\fetch-retry\index.js:127:11)
    at listOnTimeout (node:internal/timers:557:17)
    at processTimers (node:internal/timers:500:7)
Emitted 'error' event on Readable instance at:
    at emitErrorNT (node:internal/streams/destroy:157:8)
    at emitErrorCloseNT (node:internal/streams/destroy:122:3)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
  type: 'aborted'
}

Expected behavior
The error happens in index.js in the following code block:

const abort = () => {
  const error = new AbortError('The operation was aborted.');
  reject(error);
  if (request.body && request.body instanceof Stream.Readable) {
    request.body.destroy(error);   // <==== HERE IS WHERE THE UNHANDLED ERROR OCCURS!!!!
  }

  if (!response || !response.body) {
    return;
  }

  response.body.emit('error', error);
};

To fix it, you need a listener for the "error" event of the Readable stream, like this below:

const abort = () => {
  const error = new AbortError('The operation was aborted.');
  reject(error);
  if (request.body && request.body instanceof Stream.Readable) {
    request.body.on('error', ()=>{});  // You must define a listener so that potential errors when destroying the stream ar catched
    request.body.destroy(error);
  }

  if (!response || !response.body) {
    return;
  }

  response.body.emit('error', error);
};

Screenshots

Your Environment

software version
node-fetch 3.3.2
node 16.13.0
npm 8.1.0
Operating System Windows 10

Additional context
I believe this issue was reported in the past, but it was closed:
#1420

@AleCaste AleCaste added the bug label Jan 23, 2024
@willemmulder
Copy link

I had the same issue. In the end, I had to stop using node-fetch and instead used the native fetch API. The drawback is that it returns a (web) ReadableStream and not a (Node) stream.Readable.

You'll have to use it like this

const reader = stream.getReader();
while (true) {
    try {
        const { value, done } = await reader.read();
        if (done) {
            break;
        }
        // Do something
    } catch(err) {
        console.log('Error reading stream', err);
        break;
    }
}

@axonedge
Copy link

Happened to me as well, any resolution for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants