bugsnag / bugsnag-js

JavaScript error handling tool for BugSnag. Monitor and report JavaScript bugs & errors.
https://docs.bugsnag.com/platforms/javascript
MIT License
855 stars 252 forks source link

Reporting handled errors fails on Vercel serverless functions #1360

Open reegodev opened 3 years ago

reegodev commented 3 years ago

Reporting handled errors fails on Vercel serverless functions

When using Bugsnag.notify in serverless functions on Vercel, the process is terminated before Bugsnag client can effectively send the notification, resulting in a loss of events.

Sample code

This naive implementation fails to report errors because, as mentioned above, the Vercel runtime kills the process before notify is done sending.

const Bugsnag = require('@bugsnag/js')

Bugsnag.start({
  apiKey: process.env.BUGSNAG_API_KEY,
})

module.exports = async (req, res) => {
  try {
    throw new Error('A test error')
  } catch (error) {
    Bugsnag.notify(error)
    return res.status(500).send('Error')
  }

  return res.send('Success')
}

The only workaround we could find was to create a helper function that returns a promise and resolves the promise when Bugsnag.notify is done sending.

const Bugsnag = require('@bugsnag/js')
Bugsnag.start('API_KEY')

const notifyError = (error) => new Promise((resolve) => Bugsnag.notify(error, null, resolve))

Bugsnag.start({
  apiKey: process.env.BUGSNAG_API_KEY,
})

module.exports = async (req, res) => {
  try {
    throw new Error('A test error')
  } catch (error) {
    await notifyError(error)
    return res.status(500).send('Error')
  }

  return res.send('Success')
}

Using the awsLambda plugin does not help. Although Vercel serverless functions have a different signature they always receive two arguments, so the lambda plugin seems to be compatible. However the function logs report this:

[GET] /api/bugsnag
11:51:07:36
2021-04-16T09:51:07.424Z    fb2d826a-561e-46a5-9d9f-c1cca572eea0    ERROR   [bugsnag] Delivery may be unsuccessful: flush timed out after 2000ms
2021-04-16T09:51:07.448Z    e2498778-cfea-4a5a-aad8-3aa3ab13d844    ERROR   [bugsnag] Session failed to send…
Error: Client network socket disconnected before secure TLS connection was established
    at connResetException (internal/errors.js:607:14)
    at TLSSocket.onConnectEnd (_tls_wrap.js:1544:19)
    at TLSSocket.emit (events.js:327:22)
    at TLSSocket.EventEmitter.emit (domain.js:467:12)
    at endReadableNT (internal/streams/readable.js:1327:12)
    at processTicksAndRejections (internal/process/task_queues.js:80:21) Error: Client network socket disconnected before secure TLS connection was established
    at connResetException (internal/errors.js:607:14)
    at TLSSocket.onConnectEnd (_tls_wrap.js:1544:19)
    at TLSSocket.emit (events.js:327:22)
    at TLSSocket.EventEmitter.emit (domain.js:467:12)
    at endReadableNT (internal/streams/readable.js:1327:12)
    at processTicksAndRejections (internal/process/task_queues.js:80:21) {
  code: 'ECONNRESET',
  path: null,
  host: 'sessions.bugsnag.com',
  port: 443,
  localAddress: undefined
}

Is there any chance to make Bugsnag.notify return a promise if the third argument is omitted, as with most Node libraries that support both promises and callbacks? I'd be happy to provide a PR if you agree on the solution.

johnkiely1 commented 3 years ago

Hi @reegodev,

The AWS Lambda plugin should wait for any Bugsnag.notify() calls to be delivered. Could you tell me a bit more about the problems you encountered when trying to use that? Perhaps you could share how you configured your code with the plugin?

reegodev commented 3 years ago

Hi @johnkiely1 , after testing a repro i found out that its actually only Vercel functions to have this problem, the awsLambda plugins works correctly on Netlify, so i updated the issue. Sorry about that.

I created a repo you can deploy to Vercel with the button found in the readme: https://github.com/reegodev/test-bugsnag-serverless

You can trigger the error with curl <YOUR ENDPOINT>/api/bugsnag

johnkiely1 commented 3 years ago

Hi @reegodev,

From your logs it looks like the problem is that delivery times out:

Delivery may be unsuccessful: flush timed out after 2000ms

You could try increasing the flushTimeoutMs to allow it to wait longer —https://docs.bugsnag.com/platforms/javascript/aws-lambda/#flushtimeoutms

Although this is a reasonable amount of time to wait so perhaps theres an underlying network problem at fault?

There’s also an AWS Lambda API that you can opt in to, which might have a better chance of success: https://vercel.com/docs/runtimes#advanced-usage/advanced-node-js-usage/aws-lambda-api

Ultimately however we don't officially support Vercel functions as yet so it may be the case that the above suggestions will still have no effect.

Do let us know how you get on. Thanks

reegodev commented 3 years ago

Thanks, @johnkiely1 , increasing the timeout did not solve the problem, i tried with 10 seconds and received the same error.

Using the AWS Lambda API however did work. So i guess its just the custom Vercel function runtime that somehow blocks the AWS Lambda plugin. Is it worth mentioning in the AWS Lambda section of the docs that Vercel functions are only supported through the Lambda API format?

mattdyoung commented 3 years ago

@reegodev We're going to track this as a feature request for adding official support for Vercel serverless functions, but using the AWS Lambda API seems like a reasonable option in the meantime.

hansottowirtz commented 1 year ago

Might be related to this issue: https://github.com/bugsnag/bugsnag-js/issues/1875

statico commented 1 year ago

@reegodev Did you ever find a solution to this? We're seeing theses errors with Bugsnag on Vercel with Next.js.

2023-05-22T22:39:23.893Z    63d97795-12a8-44f3-xxxx-ce59ec51770f    INFO    [bugsnag] Delivery may be unsuccessful: flush timed out after 2000ms
2023-05-22T22:39:23.896Z    3595a722-ef72-462c-xxxx-e25e83d42f24    INFO    [bugsnag] Session failed to send…
Error: Client network socket disconnected before secure TLS connection was established
    at connResetException (node:internal/errors:717:14)
    at TLSSocket.onConnectEnd (node:_tls_wrap:1595:19)
    at TLSSocket.emit (node:events:525:35)
    at TLSSocket.emit (node:domain:489:12)
    at endReadableNT (node:internal/streams/readable:1359:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
hansottowirtz commented 1 year ago

@statico This is because Bugsnag doesn't correctly flush in the current request and then times out in the request that follows.

reegodev commented 1 year ago

@statico If I remember correctly we went with the Lambda API as suggested by @mattdyoung