_error.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import { withScope, captureException } from '@sentry/core';
  2. import { flushQueue } from './utils/responseEnd.js';
  3. /**
  4. * Capture the exception passed by nextjs to the `_error` page, adding context data as appropriate.
  5. *
  6. * @param contextOrProps The data passed to either `getInitialProps` or `render` by nextjs
  7. */
  8. async function captureUnderscoreErrorException(contextOrProps) {
  9. const { req, res, err } = contextOrProps;
  10. // 404s (and other 400-y friends) can trigger `_error`, but we don't want to send them to Sentry
  11. const statusCode = (res && res.statusCode) || contextOrProps.statusCode;
  12. if (statusCode && statusCode < 500) {
  13. return Promise.resolve();
  14. }
  15. // In previous versions of the suggested `_error.js` page in which this function is meant to be used, there was a
  16. // workaround for https://github.com/vercel/next.js/issues/8592 which involved an extra call to this function, in the
  17. // custom error component's `render` method, just in case it hadn't been called by `getInitialProps`. Now that that
  18. // issue has been fixed, the second call is unnecessary, but since it lives in user code rather than our code, users
  19. // have to be the ones to get rid of it, and guaraneteedly, not all of them will. So, rather than capture the error
  20. // twice, we just bail if we sense we're in that now-extraneous second call. (We can tell which function we're in
  21. // because Nextjs passes `pathname` to `getInitialProps` but not to `render`.)
  22. if (!contextOrProps.pathname) {
  23. return Promise.resolve();
  24. }
  25. withScope(scope => {
  26. if (req) {
  27. scope.setSDKProcessingMetadata({ request: req });
  28. }
  29. // If third-party libraries (or users themselves) throw something falsy, we want to capture it as a message (which
  30. // is what passing a string to `captureException` will wind up doing)
  31. captureException(err || `_error.js called with falsy error (${err})`, {
  32. mechanism: {
  33. type: 'instrument',
  34. handled: false,
  35. data: {
  36. function: '_error.getInitialProps',
  37. },
  38. },
  39. });
  40. });
  41. // In case this is being run as part of a serverless function (as is the case with the server half of nextjs apps
  42. // deployed to vercel), make sure the error gets sent to Sentry before the lambda exits.
  43. await flushQueue();
  44. }
  45. export { captureUnderscoreErrorException };
  46. //# sourceMappingURL=_error.js.map