Sentry can’t fix React hydration errors, but it can really help you debug them
Hydration failed because the initial ui does not match what was rendered on the server. Don’t you just love hate it when that happens?
If you’re building server-rendered pages with Next.js or any React-based meta-framework, you know hydration errors suck and are usually difficult to debug. Hydration in React is the process that happens when a React application that was rendered as HTML on the server is made interactive in the browser. Hydration errors happen when the markup rendered by React on the client doesn’t match the initial server-rendered HTML, or when invalid HTML was sent by the server, and React couldn’t fix it. Sometimes this is unavoidable, for example, with dates and localization. You can suppress errors for these unavoidable differences in your React code, but most hydration errors would indicate that you’ve got some bugs in your app.
This article is not about how to fix hydration errors but how to debug them using Sentry. When hydration errors happen in development, your JavaScript framework of choice will usually show you a large error message with some details about the code that triggered the error. However, hydration errors aren’t usually visible or obvious in production, and your average real-world users probably won’t be able to provide useful screenshots with error reports (and probably won’t think to look in the browser console for errors). What’s more, the automatic error issue created by Sentry won’t be very useful, either.
But wait, Session Replay has a superpower
If you’re using Sentry’s Session Replay to get reproductions of user sessions when a user triggers a hydration error:
Sentry will automatically create a specific Hydration Error Issue for you (for free!),
group all the same errors together,
capture both the server-rendered and client-rendered markup that existed when the error happened,
and show you the diffs in both visual and raw HTML modes.
Just make sure you’re using Sentry’s JavaScript SDK, version 7.87.0 or above, and you’ve got Session Replay enabled to get the good stuff.
Here’s what a grouped Hydration Error looks like in Sentry:
It is named “Hydration Error,” so you can find it easily in the issue list view.
Choose which event to view (recommended, latest, oldest) and navigate between events to compare contextual information.
View a sliding diff between the server and the client (open the diff viewer to also view a side by side visual diff and HTML diff).
Click the “Resolving Hydration Errors” link to get more help on solving hydration errors.
Debugging hydration errors
Given that the standard hydration error message states that the server-rendered HTML did not match the client-rendered HTML, the diff viewer is really helpful in finding those differences. The “Before” view is the server-rendered version, and the “After” view is what React rendered on the client.
What you might notice in this example, however, is that the “Before” and “After” versions look the same visually. When inspecting the HTML diff, we see a blank page rendered on the server and HTML rendered on the client. This isn’t correct. HTML is definitely being rendered on the server; I checked in my browser's network tab.
The real issue in the code causing the hydration error is not that the server-rendered and client-rendered HTML don’t match, it’s that my HTML is invalid (a <p>
is contained within a <p>
) and React threw an error. This is why hydration errors suck: they don’t always make sense.
So why does there appear to be no HTML rendered on the server according to the diff? Given that React threw a nonsensical hydration error for invalid HTML, Sentry can only make a best-effort guess as to what the problem is. Usually, if one event has a diff that doesn ’t make sense, another event may be more helpful. The bottom line is that when React throws a hydration error, there’s a problem that needs fixing. And because React doesn’t tell us the details needed to fix the problem in production, Sentry fills in the blanks on the hydration error diff tools as much as possible so you can better debug the problem.
Does creating hydration error issues and diffs increase my Sentry bill?
No. If you’re already using Session Replay, you get automatic grouped hydration error issues for free. Hydration error issues in Sentry are generated from Replays and their associated data, so have no impact on your error quota, either. Additionally, you’ll also get alerted on hydration errors by default.
Bonus tip: level-up your debugging by unmasking non-sensitive data in replays
If you’re using Session Replay, you might have noticed that it masks all text content with * and blocks all media elements on the client by default, before it is sent to Sentry. In this article, the examples shown in the hydration errors images show text rather than asterisks, due to how the Session Replay SDK was configured.
If you're working on a content-based website that's free of personally identifiable information (PII), you can disable the default text masking and image blocking by configuring the maskAllText
and blockAllMedia
configuration options in the Session Replay initialization.
Sentry.replayIntegration({
maskAllText: false,
blockAllMedia: false,
});
This can be really helpful in debugging fake hydration errors (that are actually invalid HTML errors) like the one demonstrated in this article.
Note: Only use this if your site has no sensitive data or if you've already set up other options for masking or blocking actual sensitive data. Read more about Session Replay privacy configuration on the Sentry docs.
Debuggability is key
Hydration errors in production have always been a bit of a mystery, without any practical way to deal with and debug them. With the Sentry Replay SDK, you now get the HTML diffs and as much context as possible with each hydration error, helping you to debug and fix things faster. And whilst this ultimately helps you as a developer, it benefits everyone else as well: stakeholders, clients, and most importantly — your users. Now, go fix those bugs.