Error: Hydration failed because the initial UI does not match what was rendered on the server.

Alon Valadji
Israeli Tech Radar
Published in
3 min readMar 3, 2024

--

Update: This annoying error has been fixed in Next.js 14.2. Now you’ll now exactly why you have an hydration error:

You know that feeling, that you are writing your new Next.js app, everything is flowing great, your components are awesome, your server components are fantastic, you are hitting that save button and then you’re getting this?

So what happened there?

Do not be scared by this error, it usually occurs when you have missing HTML markup in your server component (or SSR).

HTML

Because HTML is a forgiving markup language, it won’t force you to write “correct” markup, but will eagerly render even faulty ones.

For example:

<b> this is bold text

Will render a page with this line in bold, even if we didn’t close the <b> tag. Anything after that will also be bold, but your page will still work.

Lucky for us, React prevents us from writing an equivalent JSX and will cause an error:

So how can we still have weird Hydration Error?

TABLE

A <table> must have either a <thead> or <tbody> before adding table rows (<tr> ).

Consider this piece of code on our server component:

export function Table() {
return <table><tr><td>test</td></tr></table>;
}

It’ll be parsed and applied to the browser’s dom as follows:

<html>
<table>
<tbody>
<tr>
<th>test</th>
</tr>
</tbody>
</table>
</html>

Hence, we will get that annoying Hydration Error.

Fixing that is easy, just adding <tbody> to our table:

export function Table() {
return <table><tbody><tr><td>test</td></tr></tbody></table>
}

And now the error is gone!

Conclusion

When you get this error, check your JSX markup and see if it has missing tags the browser adds.

P.S.

If you want to see what’s the “real” HTML that renders out of your HTML, open the browser, navigate to “about:blank”, open the dev tools console, and just innerHTML your string of markup:

const str = "<table><tr><td>test</td></tr></table>";
document.documentElement.innerHTML = str;

Just print in the console the document.documentElement or inspect the newly added element to the page:

Please do comment with your thoughts, ideas, rants, mistakes, etc. Thank you for reading! 🤗

--

--

Alon Valadji
Israeli Tech Radar

Alon is a leading software architect well-versed in Rozansky and Woods’ architectural methodologies. As a full-cycle JavaScript and web architecture torchbearer