Skip to content

[BUG] Non-serializable values polluting React Router navigation state #2682

@mmeluch

Description

@mmeluch

Description/Screenshot
First of all, I'm sorry for such a long post, but I'm at my wits end as I've been investigating this issue for days and I'm no closer to fixing it (except for workarounds illustrated below).

I'm encountering a sporadic error in one of my React projects when ApplicationInsights-JS is enabled. The error occurs only when navigating using React Router (v 5.3) and passing an array in the history.state, and it happens regardless of:

  • Browser used (tested in latest Chrome, Firefox)
  • ApplicationInsights-JS version (tested multiple 3.x versions)
  • Build type (development and production)
  • SDK config (I've ran the same config in a smaller RR5 project without issues)

The error message varies based on the place that triggered it (3rd party library, my code..), but here are some occurences I was able to document:

  • DataCloneError: Failed to execute 'pushState' on 'History': function (…) could not be cloned
  • Uncaught DOMException: Function object could not be cloned

This issue does not happen at all when ApplicationInsights is disabled. I was unable to test this with newer versions of React Router since they contain a lot of breaking changes.

Image Image

Steps to Reproduce
I would love to provide reliable steps to reproduce, however, I was not able to simulate this in my other projects, so it must be some combination of the packages I'm using:

  • package.json
  • OS/Browser: Firefox 145, Chrome 143
  • SDK Version [e.g. 22]: 3.1.x/3.3.x + 17.1.2 (react-js)
  • How you initialized the SDK:
this.appInsights = new ApplicationInsights({
      config: {
        connectionString: `InstrumentationKey=${AIInstrumentationKey};IngestionEndpoint=/`,
        enableUnhandledPromiseRejectionTracking: true,
        eventsLimitInMem: 2500,
        disableInstrumentationKeyValidation: true,
        userOverrideEndpointUrl: AIEndpointUrl,
        isStorageUseDisabled: true,
        enableSessionStorageBuffer: false,
        maxBatchInterval: 10000,
        maxBatchSizeInBytes: 250000,
        extensions: [this.reactPlugin],
        extensionConfig: {
          [this.reactPlugin.identifier]: {
            history: browserHistory,
          },
        },
      },
    })

this.appInsights.loadAppInsights()

The pieces of code which tend to raise these exceptions:

history.push({
      pathname: location.pathname,
      search: searchParams.toString(),
      // Workaround for the serialization issue:
      // state: JSON.parse(JSON.stringify(location.state)),
      state: location.state, // original code
})
    const state: MultiStepFlowData = {
      // Workaround for the serialization issue:
      // ...JSON.parse(JSON.stringify(historyState ?? {})),
      ...(historyState ?? {}), // original code
      selectedIds: [...newValue],
    }
    history.replace({ state })

Expected behavior
ApplicationInsights-JS does not interfere with any other libraries in a project.

Additional context
ℹ️ After days of debugging, I was able to confirm that ApplicationInsights-JS hooks into some of the browser history APIs by monkey-patching them which, in my opinion, could be the cause of this behavior. You can also see the very same "Patching" string in one of my exception screenshots above:

_makeDynamicObject(state, target, name, "Patching");

One other place which suggests the ApplicationInsights-JS is doing something weird is this one, since the "ai_dynCfg_1" string is visible on one of the screenshots below:

export const CFG_HANDLER_LINK = symbolFor("[[ai_dynCfg_1]]");

When I inspected my history state (which I get via useLocation) in the Chrome debugger, I was able to confirm a number of deviations from a "pure" JS Array value which I get when the SDK is disabled:

  1. The value itself was accessible only via getters/setters, it wasn't available on initial hover. This probably causes no issues during usual runtime, however it might be an issue when dealing with history state
  2. The individual elements in the array contained additional Symbols and more getters/setters - see screenshots below.

The "good" (unpolluted) history state, vs. the "polluted" state:

Image Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions