sindresorhus / got

🌐 Human-friendly and powerful HTTP request library for Node.js
MIT License
14.27k stars 935 forks source link

`ERR_STREAM_PREMATURE_CLOSE` on early `destroy()` #2041

Closed longnguyen2004 closed 1 year ago

longnguyen2004 commented 2 years ago

Describe the bug

Actual behavior

When a Got stream is destroyed before it's ended (which can happen with a read timeout), an ERR_STREAM_PREMATURE_CLOSE error is thrown. Digging through the git history, it seems to have been fixed in a previous version, but the fix was lost at some point.

Expected behavior

No error is thrown

Code to reproduce

import got from "got";
import devnull from "dev-null";
import { pipeline } from "stream/promises";

const gotStream = got("https://google.com", { isStream: true });
const nullStream = devnull();
gotStream.on("response", () => gotStream.destroy());
pipeline(gotStream, nullStream);

Checklist

sarahmcdougall commented 1 year ago

Hello, I am also encountering this ERR_STREAM_PREMATURE_CLOSE error on early destroy() with Node.js version v18.12.0 and got version 11.8.6 when used as a dependency in a TypeScript project (typescript version 4.4.2). I do not experience this error with version 11.8.5 but I run into a separate onCancel error that likely gets thrown before this error would be thrown, so I am unsure if this was introduced with the recent release. Please let me know if you would like to be provided with additional code to reproduce and/or a stack trace.

longnguyen2004 commented 1 year ago

RunKit repro: https://runkit.com/longnguyen2004/627f8793f9072a000aa12ee6

szmarczak commented 1 year ago

Digging through the git history, it seems to have been fixed in a previous version, but the fix was lost at some point.

Those errors were unhandled errors.

The error is correct in this case. https://nodejs.org/api/stream.html#streamfinishedstream-options-callback

Emitting 'close' before 'end' on a Readable stream will cause an ERR_STREAM_PREMATURE_CLOSE error.

This is exactly what happens here. pipeline uses finished under the hood which throws ERR_STREAM_PREMATURE_CLOSE since the stream got closed before fully read.

When a Got stream is destroyed before it's ended (which can happen with a read timeout)

This is a separate case where TimeoutError is thrown.