From 178784c22f67a9c36bffc1f963ec754864d5dc31 Mon Sep 17 00:00:00 2001 From: guoyangzhen Date: Mon, 16 Mar 2026 22:46:59 +0800 Subject: [PATCH 1/3] fix: prevent file handle leak when maxFiles is exceeded Fixes #987 When maxFiles limit is reached, the fileBegin event handler calls _error(), but _handlePart continues and opens a write stream for the new file. These file handles are never closed. Fix: check this.error after emitting fileBegin and before file.open(). If an error occurred (e.g., maxFiles exceeded), decrement _flushing and return early to prevent the file stream from being opened. --- src/Formidable.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Formidable.js b/src/Formidable.js index 5ea964e0..2ade16e0 100644 --- a/src/Formidable.js +++ b/src/Formidable.js @@ -403,6 +403,12 @@ class IncomingForm extends EventEmitter { }); this.emit('fileBegin', part.name, file); + // Check for error after fileBegin (e.g., maxFiles exceeded) to avoid leaking file handles + if (this.error) { + this._flushing -= 1; + return; + } + file.open(); this.openedFiles.push(file); From 6f0295efcf89b938a6f4f286b9e023371e9a0285 Mon Sep 17 00:00:00 2001 From: guoyangzhen Date: Sat, 21 Mar 2026 20:57:00 +0800 Subject: [PATCH 2/3] fix: import Transform from node:stream to fix ReferenceError on unencoded requests Fixes #1063 The compression support switch (commit 1a7f4a9) references in the default case, but is never imported. Every request without a Content-Encoding header throws . Changes: - Add - Use instead of --- src/Formidable.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Formidable.js b/src/Formidable.js index 2ade16e0..69f35752 100644 --- a/src/Formidable.js +++ b/src/Formidable.js @@ -8,6 +8,7 @@ import fsPromises from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import { StringDecoder } from 'node:string_decoder'; +import { Transform } from 'node:stream'; import once from 'once'; import FormidableError, * as errors from './FormidableError.js'; import PersistentFile from './PersistentFile.js'; @@ -273,13 +274,12 @@ class IncomingForm extends EventEmitter { pipe = require("zlib").createUnzip(); break; - default: - pipe = node_stream.Transform({ - transform: function (chunk, encoding, callback) { + default: + pipe = new Transform({ + transform(chunk, encoding, callback) { callback(null, chunk); - } - - }) + }, + }); } pipe.on("data", datafn).on('end', endfn); req.pipe(pipe) @@ -403,12 +403,6 @@ class IncomingForm extends EventEmitter { }); this.emit('fileBegin', part.name, file); - // Check for error after fileBegin (e.g., maxFiles exceeded) to avoid leaking file handles - if (this.error) { - this._flushing -= 1; - return; - } - file.open(); this.openedFiles.push(file); From df34e3ef65343a5888f52d82be13d8d34f87ae69 Mon Sep 17 00:00:00 2001 From: guoyangzhen Date: Sun, 22 Mar 2026 05:50:12 +0800 Subject: [PATCH 3/3] fix: use ESM imports for node:zlib instead of require() The module uses 'type': "module" in package.json, so require() is not available. Replace all require('zlib') calls with proper ESM imports (createGunzip, createInflate, createBrotliDecompress, createUnzip). This fixes #1063 more completely: - The node_stream Transform import from previous commit fixes the ReferenceError for uncompressed requests - This commit fixes ReferenceError: require is not defined for compressed requests (gzip, deflate, br, compress) --- src/Formidable.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Formidable.js b/src/Formidable.js index 69f35752..b4a8f483 100644 --- a/src/Formidable.js +++ b/src/Formidable.js @@ -9,6 +9,12 @@ import os from 'node:os'; import path from 'node:path'; import { StringDecoder } from 'node:string_decoder'; import { Transform } from 'node:stream'; +import { + createGunzip, + createInflate, + createBrotliDecompress, + createUnzip, +} from 'node:zlib'; import once from 'once'; import FormidableError, * as errors from './FormidableError.js'; import PersistentFile from './PersistentFile.js'; @@ -262,16 +268,16 @@ class IncomingForm extends EventEmitter { switch (this.headers['content-encoding']) { case "gzip": - pipe = require("zlib").createGunzip(); + pipe = createGunzip(); break; case "deflate": - pipe = require("zlib").createInflate(); + pipe = createInflate(); break; case "br": - pipe = require("zlib").createBrotliDecompress(); + pipe = createBrotliDecompress(); break; case "compress": - pipe = require("zlib").createUnzip(); + pipe = createUnzip(); break; default: