From 51387eade9b01008cdd0d66640b15ba99a4f6068 Mon Sep 17 00:00:00 2001 From: LeSingh1 Date: Fri, 10 Jul 2026 07:34:44 -0700 Subject: [PATCH 1/2] fix: expose InvalidJSONFieldError and NoFormData in multipartErrors --- index.js | 4 ++- test/multipart-json.test.js | 70 +++++++++++++++++++++++++++++++++++-- types/index.d.ts | 3 ++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index e22ddc03..1e33f7b3 100644 --- a/index.js +++ b/index.js @@ -181,7 +181,9 @@ function fastifyMultipart (fastify, options, done) { InvalidMultipartContentTypeError, RequestFileTooLargeError, FileBufferNotFoundError, - PrematureCloseError + PrematureCloseError, + InvalidJSONFieldError, + NoFormData }) fastify.addContentTypeParser('multipart/form-data', setMultipart) diff --git a/test/multipart-json.test.js b/test/multipart-json.test.js index 9e9da6fb..3c3c09f7 100644 --- a/test/multipart-json.test.js +++ b/test/multipart-json.test.js @@ -141,7 +141,7 @@ test('should not parse JSON fields forms if non-json content-type is set', funct }) test('should throw error when parsing JSON fields failed', function (t, done) { - t.plan(2) + t.plan(3) const fastify = Fastify() t.after(() => fastify.close()) @@ -188,7 +188,7 @@ test('should throw error when parsing JSON fields failed', function (t, done) { }) test('should always reject JSON parsing if the value was truncated', function (t, done) { - t.plan(2) + t.plan(3) const fastify = Fastify() t.after(() => fastify.close()) @@ -409,3 +409,69 @@ test('should return 400 when the field validation fails', function (t, done) { form.pipe(req) }) }) + +test('multipartErrors should expose InvalidJSONFieldError', async function (t) { + t.plan(2) + + const fastify = Fastify() + t.after(() => fastify.close()) + + fastify.register(multipart) + await fastify.ready() + + t.assert.ok(fastify.multipartErrors.InvalidJSONFieldError, 'InvalidJSONFieldError is exposed on multipartErrors') + t.assert.strictEqual(typeof fastify.multipartErrors.InvalidJSONFieldError, 'function') +}) + +test('thrown InvalidJSONFieldError should be an instance of multipartErrors.InvalidJSONFieldError', function (t, done) { + t.plan(3) + + const fastify = Fastify() + t.after(() => fastify.close()) + + fastify.register(multipart) + + fastify.post('/', async function (req, reply) { + try { + for await (const part of req.parts()) { + t.assert.strictEqual(typeof part.value, 'string') + } + reply.code(200).send() + } catch (error) { + t.assert.ok(error instanceof fastify.multipartErrors.InvalidJSONFieldError) + t.assert.strictEqual(error.code, 'FST_INVALID_JSON_FIELD_ERROR') + reply.code(error.statusCode).send() + } + }) + + fastify.listen({ port: 0 }, function () { + const boundary = 'testboundary' + const body = [ + '--' + boundary, + 'Content-Disposition: form-data; name="jsonfield"', + 'Content-Type: application/json', + '', + 'not valid json', + '--' + boundary + '--', + '' + ].join('\r\n') + + const opts = { + hostname: '127.0.0.1', + port: fastify.server.address().port, + path: '/', + method: 'POST', + headers: { + 'content-type': 'multipart/form-data; boundary=' + boundary, + 'content-length': Buffer.byteLength(body) + } + } + + const req = http.request(opts, res => { + t.assert.strictEqual(res.statusCode, 406) + res.resume() + res.on('end', done) + }) + req.end(body) + }) +}) diff --git a/types/index.d.ts b/types/index.d.ts index 6a8a5426..26e9545c 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -62,7 +62,10 @@ interface MultipartErrors { PrototypeViolationError: FastifyErrorConstructor; InvalidMultipartContentTypeError: FastifyErrorConstructor; RequestFileTooLargeError: FastifyErrorConstructor; + FileBufferNotFoundError: FastifyErrorConstructor; PrematureCloseError: FastifyErrorConstructor; + InvalidJSONFieldError: FastifyErrorConstructor; + NoFormData: FastifyErrorConstructor; } declare namespace fastifyMultipart { From 0a03ca67fc059b37041d864ae880acaa5dfcd7fa Mon Sep 17 00:00:00 2001 From: LeSingh1 Date: Mon, 13 Jul 2026 12:35:03 -0700 Subject: [PATCH 2/2] test: assert InvalidJSONFieldError and NoFormData in multipartErrors type tests --- types/index.tst.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/types/index.tst.ts b/types/index.tst.ts index 949de7bf..11aac220 100644 --- a/types/index.tst.ts +++ b/types/index.tst.ts @@ -165,7 +165,9 @@ const runServer = async () => { expect(app.multipartErrors.FieldsLimitError).type.toBe() expect(app.multipartErrors.FilesLimitError).type.toBe() + expect(app.multipartErrors.InvalidJSONFieldError).type.toBe() expect(app.multipartErrors.InvalidMultipartContentTypeError).type.toBe() + expect(app.multipartErrors.NoFormData).type.toBe() expect(app.multipartErrors.PartsLimitError).type.toBe() expect(app.multipartErrors.PrototypeViolationError).type.toBe() expect(app.multipartErrors.RequestFileTooLargeError).type.toBe()