Skip to content

Conversation

@sullvn
Copy link

@sullvn sullvn commented Jan 16, 2026

Summary

This PR fixes broken CSS styles which can occur while recording a session replay. It happens when the client is using a CSS-in-JS library to create styles, and there is a single bad CSS rule somewhere.

Session replay already has explicit support for styled-components, but it has two problems:

  • Does not support other CSS-in-JS libraries which use CSSGroupingRule.insertRule, such as stitches
  • The support check seems to be a Chrome-only check, without support for Safari or Firefox

This is a critical issue for my team, as we cannot use session replay at all if there's a possibility broken styles occur while recording. Even worse, the failure seems to cascade, producing more and more broken styles.

Details

After investigation and testing, I believe I have a full understanding of the problem:

  1. Session replay wraps various DOM functions for tracking
  2. Session replay has an error handler for these wrapped DOM functions. This error handler has explicit logic to rethrow errors from the inner functions, as some libraries expect these errors. Such as styled-components.
  3. This logic checks for CSSStyleSheet.insertRule
  4. However, other CSS-in-JS libraries, such as stitches, also use CSSGroupingRule.insertRule
  5. In the case of stitches, it maintains an index counter, and expects to see an error when there's an error, so it can skip incrementing the index
  6. Session replay swallows the error here, making stitches' index faulty
  7. So when we give stitches a bad CSS rule, an error occurs, triggering this process, and producing broken styles. This error state only worsens over time.

An example bad selector is this:

/* WRONG */
&:not:has([data-bad-selector]) {
}

/* RIGHT */
&:not(:has([data-good-selector])) {
}

The problem code in the session replay implementation:

// styled-components relies on this error being thrown and bubbled up, rrweb is otherwise suppressing it
if (typedError.message.includes('insertRule') && typedError.message.includes('CSSStyleSheet')) {
throw typedError;
}

As an example, here is where the problem breaks stitches:

https://github.com/stitchesjs/stitches/blob/50fd8a1adc6360340fe348a8b3ebc8b06d38e230/packages/core/src/sheet.js#L189

try {
  groupingRule.insertRule(cssText, index)

  ++index
} catch (__) {
  // do nothing and continue
}

Proposed solution

A desired solution would be one that supports both CSSStyleSheet.insertRule and CSSGroupingRule.insertRule, while also supporting the various error formats created by the different browsers.

An even better solution would be one which avoids parsing string values from return errors. However, in lieu of a bigger refactor to do so, I've examined the various returned browser errors and have come up with this simple change:

// Supports CSSStyleSheet and CSSGroupingRule within Chrome, Safari, and Firefox
if (typedError.stack?.includes('insertRule')) {
  throw typedError;
}

Here's an example error in each browser for comparison:

Chrome Safari Firefox
Chrome Safari Firefox

Checklist

  • Does your PR title have the correct title format?
  • Does your PR have a breaking change?: No

Note

Improves compatibility with CSS-in-JS during capture to prevent suppressed errors from breaking styles.

  • Updates errorHandler to rethrow when typedError.stack includes insertRule, covering both CSSStyleSheet.insertRule and CSSGroupingRule.insertRule
  • Broadens support beyond Chrome to Safari and Firefox; clarifies comments accordingly

Written by Cursor Bugbot for commit 77a9556. This will update automatically on new commits. Configure here.

@macroscopeapp
Copy link
Contributor

macroscopeapp bot commented Jan 16, 2026

Broaden session-replay.SessionReplay rrweb errorHandler rethrow condition to cover CSS-in-JS recording issues in session-replay.ts

Change the rrweb errorHandler to rethrow when the error stack includes insertRule, and update comments to note CSSStyleSheet.insertRule and CSSGroupingRule.insertRule.

📍Where to Start

Start with the rrweb errorHandler logic in session-replay.ts.


Macroscope summarized 77a9556.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant