Skip to content

Commit b49cd03

Browse files
HaidongPangsholladay
andauthoredMar 19, 2025··
Fix memory leak, clean up body streams after retry (#651)
Fixes #650 Co-authored-by: Seth Holladay <me@seth-holladay.com>
1 parent 5dc572d commit b49cd03

File tree

3 files changed

+9
-1
lines changed

3 files changed

+9
-1
lines changed
 

‎.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
node-version:
13-
- 18
13+
- 22
1414
steps:
1515
- uses: actions/checkout@v4
1616
- uses: actions/setup-node@v4

‎package.json

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"@typescript-eslint/no-unsafe-return": "off",
8787
"@typescript-eslint/no-unsafe-call": "off",
8888
"@typescript-eslint/naming-convention": "off",
89+
"@typescript-eslint/no-unnecessary-type-assertion": "off",
8990
"n/no-unsupported-features/node-builtins": "off"
9091
}
9192
},

‎source/core/Ky.ts

+7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ export class Ky {
3636

3737
// Delay the fetch so that body method shortcuts can set the Accept header
3838
await Promise.resolve();
39+
// Before using ky.request, _fetch clones it and saves the clone for future retries to use.
40+
// If retry is not needed, close the cloned request's ReadableStream for memory safety.
3941
let response = await ky._fetch();
4042

4143
for (const hook of ky._options.hooks.afterResponse) {
@@ -64,6 +66,11 @@ export class Ky {
6466
throw error;
6567
}
6668

69+
// Now that we know a retry is not needed, close the ReadableStream of the cloned request.
70+
if (!ky.request.bodyUsed) {
71+
await ky.request.body?.cancel();
72+
}
73+
6774
// If `onDownloadProgress` is passed, it uses the stream API internally
6875
if (ky._options.onDownloadProgress) {
6976
if (typeof ky._options.onDownloadProgress !== 'function') {

0 commit comments

Comments
 (0)
Please sign in to comment.