Troubleshooting

Troubleshooting Session Replay-specific Issues

My `canvas` elements aren't getting captured

Canvas is supported in SDK versions >= 7.98.0. Please see the canvas setup documention to get started with canvas recordings.

If you are on a supported SDK version and your canvas elements still aren't getting captured, check if you have images or videos loaded from foreign origins inside your canvas. Any data loaded from an origin without CORS approval is not considered secure and will throw a SecurityError when trying to use the replay canvas integration. To fix this issue, set crossorigin="anonymous" to your images or videos. This will allow images that are loaded from foreign origins to be used in canvas as if they have been loaded from the current origin. See the CORS documention for more information about cross-origin access.

Replay is slowing down my `canvas`

The integration needs to enable preserveDrawingBuffer to export images from 3D and WebGL canvases. This can negatively affect canvas performance. If your canvas application is impacted by enabling preserveDrawingBuffer, you'll need to enable manual snapshotting and call a snapshot() method inside of your re-paint loop.

My custom CSS/images/fonts/media aren't appearing when I view the Replay

The replay 'video' is actually a video-like reproduction of the HTML on your website. This means that all the external resources your site uses (CSS/Images/Fonts), will be rendered by the corresponding <style>, <img> and <video> tags on your site. Add sentry.io to your CORS policy so the iframe hosted on sentry.io can fetch and display these resources.

Note that only static, publicly hosted videos (for example, src="./my-video.mp4") can be captured by Replay. Streamed videos and similar are not supported.

Why can't I see the full HTTP request body or all the headers?

By default, Replay will capture basic information about all outgoing fetch and XHR requests in your application. This includes the URL, request and response body size, method, and status code. The intention is to limit the chance of collecting private data. You can configure the SDK to capture bodies and additional headers.

Another reason you might not see the body is if the format is not supported. We only capture text-based bodies, including JSON, XML, FormData, and similar data types. Any captured body will be truncated to 150k characters. When we identify the body as JSON, we will try to truncate it while keeping the payload valid JSON. Bodies of byte, file, or media types are not captured.

More details about this feature can be found in the configuration page.

The SDK is slowing down my website.

If you're experiencing slowdowns on your website, first make sure you're on the latest version of our SDK, which will have the most up-to-date bug fixes and performance improvements.

We've identified two major potential reasons for impacted performance and have added several performance degradation safeguards as a result. The two culprits are websites that have a large numbers of mutations (Read the entry below to learn more.) and large console messages.

To mitigate these problems, SDK version 7.54.0 will truncate console messages and disable Replay recordings on pages that have a large number of mutations.

If you're having any problems with the latest SDK version, we want to hear about it. Please open a GitHub issue and describe your situation.

Using Session Replay increases the bundle size of my application.

Because of the complexity of the browser environment, there's a significant amount of code necessary in order for Session Replay to work. And while enabling Session Replay will add about 50 kb (gzipped) to your application bundle, we believe the benefits will outweigh the cost.

We're always working on ways to reduce the bundle size. Additionally, there are steps you can take in order to reduce the size of Session Replay based on your specific use case. See Tree Shaking for more information.

How does Rage Click detection work?

The Replay SDK tries to detect cases where a user clicked on something, but nothing happened. This is called a "Dead Click" -- a click that seems to be "dead" and does nothing, from the user's perspective. This can happen if a bug prevents the UI from being correctly updated after a button is clicked.

The way that the Replay SDK detects this is by checking if a click on a <button> or <a> element doesn't lead to either updates to the DOM or a page scroll. If within 7 seconds no updates are detected, the SDK will generate a "Slow Click" in the Replay UI. (We call it a "Slow Click" because it may be possible that something will happen after the 7s, but we chose this as a cutoff time.)

Another concept related to this is "Rage Clicks". A "Rage Click" is when a user clicks on an element many times, which indicates frustration that something isn't working.

When a Slow Click and a Rage Click come together, we have a very good indicator that something is actually wrong, and the Replay SDK will generate a "Rage Click" for this.

Note that there are some limitations to this. On the one hand, there may be false negatives -- we cannot detect all cases; for example, imagine a user clicks a "dead" button, but then clicks a different button afterwards that leads to a DOM update. In this case, since we cannot attribute the DOM update to a specific button, we'll not capture this slow click.

On the other hand, there may be false positives. For example, if a user clicks a link that leads to a file download, there is no reliable way to detect that a download was initiated, so a Slow Click may be generated even if the button is not actually "dead". For these cases, you can configure the SDK via slowClickIgnoreSelectors - see Configuration for more details.

For example, you could ignore detection of dad and rage clicks for download links in your application like this:

Copied
Sentry.replayIntegration({
  slowClickIgnoreSelectors: [
    '.download',
    // Any link with a label including "download" (case-insensitive)
    'a[label*="download" i]',
  ],
});

I see the message: "A large number of mutations was detected (N). This can slow down the Replay SDK and impact your customers."

The Sentry SDK attempts to minimize potential performance overhead in a few different ways. For example, by keeping track of the number of DOM mutations that are happening then disabling recording when a large number of changes are detected. Many simultaneous mutations can slow down a web page whether Session Replay is installed or not, but when a large number of mutations happen, the Replay client can incur an additional slowdown because it records each change.

If you're seeing the "A large number of mutations was detected" message while watching a replay, it means that your page could be optimized. For example, a dropdown list with thousands of entries could be refactored so that rows are virtualized where only the visible rows are rendered in the DOM. Another potential solution is to paginate the results fetch more data as the user scrolls through it. The SDK has a configuration that allows you to configure the limits before recording stops.

Text in the iframe isn't masked

Our masking logic doesn't run on iframe content that's provided using the srcdoc attribute, rather than loaded in via src.

To hide this content, block the iframe, as described in our Session Replay Privacy docs.

Replay on my browser extension doesn't work

This is not a supported use-case. The replay package is built to work on a website and not as an externally-loaded script via browser extension or other mechanism. In fact, Sentry's Session Replay product can help developers find out when a third-party Chrome extension causes otherwise hard to debug or reproduce issues with their website.

Response data for Apollo GraphQL Client network requests is not captured

Apollo Client sends an abort signal via AbortController whenever a query completes, to clean up and cancel all in-flight queries. When this happens, the Replay can't capture the response body because the request is handled as aborted before Replay can access the response.

To avoid this, disable this behavior of Apollo Client by configuring your own abort signal:

Copied
const abortController = new AbortController();

const httpLink = createHttpLink({
  // ... other options
  fetchOptions: {
    signal: abortController.signal, // overwrite the default abort signal
  },
});

With this configuration, Replay is able to capture response bodies from Apollo Client requests.

Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").