sentry-javascript: JSON Serialization error with circular reference

Package + Version

  • @sentry/browser
  • @sentry/node
  • raven-js
  • raven-node (raven for node)
  • other:

Version:

5.4.3,5.5.0

Description

When serializing an event/error that contains a circular reference, a browser error occurs, and then that error is logged, losing the original error.

Repro steps: open a console with sentry SDK loaded and initialized, run:

var obj = {};
obj.repro = obj;
Sentry.captureEvent(obj);

Logged stack trace in Sentry from the above:

TypeError
Converting circular structure to JSON
    --> starting at object with constructor 'Object'
    --- property 'repro' closes the circle
<anonymous> in JSON.stringify
../src/transports/fetch.ts in sendEvent at line 15:18
../../core/src/basebackend.ts in sendEvent at line 96:21
../../core/src/baseclient.ts in onfulfilled at line 353:32
../../utils/src/syncpromise.ts in onSuccess at line 127:21
../../utils/src/syncpromise.ts at line 86:52
<anonymous> in Array.forEach
../../utils/src/syncpromise.ts in _executeHandlers at line 86:22
../../utils/src/syncpromise.ts in _attachHandler at line 96:10
../../utils/src/syncpromise.ts in callback at line 106:12
../../utils/src/syncpromise.ts in new n at line 42:7
../../utils/src/syncpromise.ts in then at line 105:12
../../core/src/baseclient.ts in callback at line 342:46
../../utils/src/syncpromise.ts in new n at line 42:7
../../core/src/baseclient.ts in _processEvent at line 341:12
../../core/src/baseclient.ts in method at line 135:10
../../hub/src/hub.ts in _invokeClient at line 81:27
../../hub/src/hub.ts in method at line 223:10
../../minimal/src/index.ts in callOnHub at line 13:17
../../minimal/src/index.ts in Object.n.captureEvent at line 64:10
<anonymous> at line 3:8

Link to affected production issue in Sentry (my guess is that this is an error involving the Datatables JS library, not sure though): https://sentry.io/organizations/grasp-and-grow/issues/1107636848/

I see similar issues, but they seem to involve memory consumption and crashes.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 21 (10 by maintainers)

Most upvoted comments

We’re using the ASP.NET bundling for that, it looks like it doesn’t support source mapping out of the box. I’m trying to put together a codepen but can’t get it to trigger the same issue. Having trouble getting around CORS things with codepen to hit the exact code path - I will update if I can get a simple repro for you.

We already do this for Events, but it requires onerror data to be in place. Here we’d have to assume that a message can be either string or this event object, which is non-standard in any format. This would simply require too much additional boilerplate to handle, and it’s the first time I see such behaviour in the wild.

It won’t be the most beautiful error report you’ll ever see, but when paired with $.fn.dataTable.ext.errMode = 'throw'; you’ll get necessary information. See: https://datatables.net/manual/tech-notes/7

Patched here: https://github.com/getsentry/sentry-javascript/pull/2302

@schmod did some research around your issue, and there are two things. One bad, it’s no-fix in our codebase, and one good, if you update node to v11.12.0+, your issue will solve itself.

The problem here, is that when you use requestHandler, you create an instance of domain that has to be there in order to create an execution context for all the requests.

Once it’s there, node internally attaches it to all the promises that are created inside the lifecycle of a given domain. What happens then, is your promise has a domain key, which in itself contains a reference to req and res of the middleware.

When you try to call JSON.stringify on it, it’s trying to serialize promise.domain.req, which references res and other way around.

promise.domain.req.res === promise.domain.res;
promise.domain.res.req === promise.domain.req

The same thing would happen if you try to serialize them directly:

app.use('/', (req, res) => {
  // both calls would break
  JSON.stringify(req);
  JSON.stringify(res);
});

Thankfully, it has been fixed in version 11.12 of Node, so it shouldn’t be an issue after upgrade. Till then, Promises are simply non-serializable objects, especially when done manually like you did above, as we cannot patch JSON.stringify.

Reference:

https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V11.md#2019-03-15-version-11120-current-bridgear

[56adebf789] - domain: set .domain non-enumerable on resources (Jordan Harband) #26210