nest
nest copied to clipboard
Exception handler with Fastify leaks internals if content type is set
Is there an existing issue for this?
- [X] I have searched the existing issues
Current behavior
import { Controller, Get, Header } from '@nestjs/common';
@Controller()
export class AppController {
@Get()
@Header('Content-Type', 'text/xml')
get(): string {
throw new Error();
// return 'ok';
}
}
Throw an error:
[1635460397235] ERROR (6802 on MacBook-Pro.fritz.box): Promise errored, but reply.sent = true was set
reqId: "req-1"
err: {
"type": "FastifyError",
"message": "Attempted to send payload of invalid type 'object'. Expected a string or Buffer.",
"stack":
FastifyError: Attempted to send payload of invalid type 'object'. Expected a string or Buffer.
at onSendEnd (/Users/thomaschaaf/develop/x/x-api/node_modules/fastify/lib/reply.js:430:11)
at onSendHook (/Users/thomaschaaf/develop/x/x-api/node_modules/fastify/lib/reply.js:390:5)
at _Reply.Reply.send (/Users/thomaschaaf/develop/x/x-api/node_modules/fastify/lib/reply.js:193:3)
at FastifyAdapter.reply (/Users/thomaschaaf/develop/x/x-api/node_modules/@nestjs/platform-fastify/adapters/fastify-adapter.js:46:29)
at ExceptionsHandler.handleUnknownError (/Users/thomaschaaf/develop/x/x-api/node_modules/@nestjs/core/exceptions/base-exception-filter.js:38:24)
at ExceptionsHandler.catch (/Users/thomaschaaf/develop/x/x-api/node_modules/@nestjs/core/exceptions/base-exception-filter.js:17:25)
at ExceptionsHandler.next (/Users/thomaschaaf/develop/x/x-api/node_modules/@nestjs/core/exceptions/exceptions-handler.js:16:20)
at Object.<anonymous> (/Users/thomaschaaf/develop/x/x-api/node_modules/@nestjs/core/router/router-proxy.js:13:35)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
"name": "FastifyError",
"code": "FST_ERR_REP_INVALID_PAYLOAD_TYPE",
"statusCode": 500
}
and results in a response like this:
{
"statusCode": 500,
"code": "FST_ERR_REP_INVALID_PAYLOAD_TYPE",
"error": "Internal Server Error",
"message": "Attempted to send payload of invalid type 'object'. Expected a string or Buffer."
}
Minimum reproduction code
See above
Steps to reproduce
No response
Expected behavior
Should not pass fastify error to the enduser
Package
- [ ] I don't know. Or some 3rd-party package
- [ ]
@nestjs/common
- [ ]
@nestjs/core
- [ ]
@nestjs/microservices
- [ ]
@nestjs/platform-express
- [X]
@nestjs/platform-fastify
- [ ]
@nestjs/platform-socket.io
- [ ]
@nestjs/platform-ws
- [ ]
@nestjs/testing
- [ ]
@nestjs/websockets
- [ ] Other (see below)
Other package
No response
NestJS version
8.1.2
Packages versions
- @nestjs/[email protected]
- @nestjs/[email protected]
- @nestjs/[email protected]
- @nestjs/[email protected]
Node.js version
No response
In which operating systems have you tested?
- [X] macOS
- [ ] Windows
- [ ] Linux
Other
No response
I faced the same issue. I was trying to set application/pdf
value in the Content-Type
but got the same error code FST_ERR_REP_INVALID_PAYLOAD_TYPE
@Get('/export')
@Header('Content-Type', 'application/pdf')
export(): Promise<Buffer> {
return this.service.generatePDF();
}
Here's a repo reproducing this: https://gitlab.com/micalevisk/nestjs-issue-8469
For some reason, when FastifyAdapter
is used, the following line is evaluated twice
https://github.com/nestjs/nest/blob/411ef5e237b487c447e6b28fafaf3914ffa75778/packages/platform-fastify/adapters/fastify-adapter.ts#L293
(after adding console.log({body})
before L293 above)
which means that the following function is running twice
https://github.com/nestjs/nest/blob/775a34853a2ab97c38e021c96c6a4ed2de7815fb/packages/core/exceptions/base-exception-filter.ts#L25
first with exception
being the user-land error, and the other one being FastifyError
.
While when using ExpressAdapter
it's not (which is expected):
When @Header('Content-Type', 'application/pdf')
is not used (fastify):
Well, so this one is problematic. The default, built-in exception filter automatically converts all errors to a JSON-compatible format (to respond with the "Internal server error" in case it received an unexpected error it cannot recognize/classify).
Now, if you change the content type to, let's say, application/pdf
(or XML), Fastify throws an exception because the exception filter automatically tries to respond with the JSON object. However, we can't really add checks for all possible content types (because that wasn't the goal from the early beginning) you could potentially use in your app to the exception filter. I'm not even sure if we should classify this as a "bug", instead, I think we should just add a warning (within the filter) that the default response format is JSON and if you want to auto-react to errors thrown from within handlers that support xml/etc you should attach a custom filter (to format the error accordingly).
any idea how to solve this? I want to return Buffer but i cannot. I cannot believe that there is an issue to return other format in Fastify like pdf or so...
@vytautas-pranskunas- I believe an workaround would be using your own expection filter that catches everything (like this one)
Let's track this here https://github.com/nestjs/nest/pull/10474