question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Bug]: Error: Cannot set headers after they are sent to the client

See original GitHub issue

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

I have an endpoint in my NestJS application that responds with image instead of json:

@Get('/og/:hash')
async getOpenGraphImage(@Param('hash') hash: string, @Res() response: Response): Promise<Response<Buffer>> {
  const imageBuffer = await this.ogImageService.getImageBuffer(hash);

  return response.setHeader('Content-Type', 'image/png').send(imageBuffer);
}

But whenever I try to hit this endpoint I see the following error in the terminal:

This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason:
Error: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:371:5)
    at ServerResponse.setHeader (node:_http_outgoing:576:11)
    at ServerResponse.header (/home/goodwin/flaut-nestjs/node_modules/express/lib/response.js:776:10)
    at ServerResponse.send (/home/goodwin/flaut-nestjs/node_modules/express/lib/response.js:170:12)
    at ServerResponse.json (/home/goodwin/flaut-nestjs/node_modules/express/lib/response.js:267:15)
    at ExpressAdapter.reply (/home/goodwin/flaut-nestjs/node_modules/@nestjs/platform-express/adapters/express-adapter.js:36:57)
    at ExceptionsHandler.handleUnknownError (/home/goodwin/flaut-nestjs/node_modules/@nestjs/core/exceptions/base-exception-filter.js:38:24)
    at ExceptionsHandler.catch (/home/goodwin/flaut-nestjs/node_modules/@nestjs/core/exceptions/base-exception-filter.js:17:25)
    at ExceptionsHandler.next (/home/goodwin/flaut-nestjs/node_modules/@nestjs/core/exceptions/exceptions-handler.js:16:20)
    at /home/goodwin/flaut-nestjs/node_modules/@nestjs/core/router/router-proxy.js:13:35

Minimum reproduction code

Private repo with copyrighted codebase

Steps to reproduce

No response

Expected behavior

Ogma should verify if the response has already been sent by checking out the value of res.headersSent

Package(s) version

  • @ogma/nestjs-module: 3.1.1
  • @ogma/platform-express: 3.0.1

Node.js version

16.13.2

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
abriginetscommented, Feb 3, 2022

Oh, I didn’t mention in the docs that StreamableFile can accept not only a stream but also a buffer. I was able to achieve full compatibility with Ogma for both simple and more complex endpoints:

@Get('/location/code/:code/width/:width/height/:height/extension/:extension')
@Header('Content-Disposition', 'inline')
async getLocationImage(
  @Param('code') code: string,
  @Param('width', new ParseIntPipe()) width: number,
  @Param('height', new ParseIntPipe()) height: number,
  @Param('extension', new LocationImageExtensionValidationPipe()) extension: LocationImageFormatEnum,
  @Res({ passthrough: true }) response: Response,
): Promise<StreamableFile> {
  const imageBuffer = await this.imageLocationService.getLocationImage(code, width, height, extension);

  response.setHeader('Content-Type', mime.contentType(extension) as string);

  return new StreamableFile(imageBuffer);
}

@Get('/og/:hash')
@Header('Content-Disposition', 'inline')
@Header('Content-Type', 'image/png')
async getOpenGraphImage(@Param('hash') hash: string): Promise<StreamableFile> {
  const imageBuffer = await this.ogImageService.getImageBuffer(hash);

  return new StreamableFile(imageBuffer);
}

To summarize:

  • @Header('Content-Type', 'image/png') decorator can be used to set image format declarative way
  • To set image type imperatively response.setHeader('Content-Type', imageFormat); notation can be used for cases when image format depends on request parameters, but @Res decorator must be used with passthrough option set to true.
  • Also I’m using @Header('Content-Disposition', 'inline') to disable “download the file” behavior in the browser because Nest appends Content-Disposition: null header by default when StreamableFile is returned.

All of the above helped me to achieve the absolute same behavior decleratively compared to what I had before imperatively. Thank you!

0reactions
jmcdo29commented, Feb 3, 2022

You can also pass a second parameter to the StreamableFile’s constructor for setting content dispositions and such. Glad you were able to make it work. I’ll go ahead and close out the issue, as it’s something at Nest’s level, but I’ll keep an eye on this if you need anything else

Read more comments on GitHub >

github_iconTop Results From Across the Web

Error: Can't set headers after they are sent to the client
The error "Error: Can't set headers after they are sent." means that you're already in the Body or Finished state, but some function...
Read more >
Cannot set headers after they are sent to the client in JS
The "Cannot set headers after they are sent to the client" error occurs when the server in an express.js application sends more than...
Read more >
Cannot set headers after they are sent to the client | End Your If
Why am I receiving the error message can't set headers after they are sent to the client Nodejs? · Calling the request handler...
Read more >
[ERR_HTTP_HEADERS_SENT]: Cannot set headers after ...
I 've been running into this issue, but have not been able to produce it locally, only in a remote server. This error...
Read more >
“Can't set headers after they are sent to the client” error in ...
“Can't set headers after they are sent to the client” is one of the most common errors in Express.js. This error occurs when...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found