Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streaming ErrorBoundaries where Boundary is flushed before error cause Hydration Mismatch Error #1917

Closed
ofarukaydin opened this issue Oct 14, 2023 · 5 comments
Labels
bug Something isn't working

Comments

@ofarukaydin
Copy link

ofarukaydin commented Oct 14, 2023

Describe the bug

I don't know what causes it. I could reproduce it in stackblitz. This is a very strange hydration error. While this happens everytime in stackblitz, we get this error only like 40% of the time in our project. We have to constantly refresh in order to get this error. Makes it very hard to understand what is the root cause.

Your Example Website or App

https://stackblitz.com/edit/github-fk8exj-gi8mmw?file=src%2Froot.tsx,src%2Froutes%2Findex.tsx

Steps to Reproduce the Bug or Issue

  1. Go to stackblitz
  2. Open console
  3. See the error

Expected behavior

I expect not to have hydration error in this simple example

Screenshots or Videos

No response

Platform

  • OS: Linux
  • Browser: Chrome
  • Version: 1.8.1

Additional context

No response

@jules-sommer
Copy link

jules-sommer commented Oct 14, 2023

I too ran into this with my app when updating to the latest 1.8.1 release, with no changes made to source code. I see that downgrading the StackBlitz demo to the previous version of solid-js, i.e below in package.json:

"solid-js": "1.7.12"

Solves the hydration error.

The stack trace is also pretty similar, nearly identical in fact, though in your repro the actual hydration key seems to exist in the DOM whereas mine does not ( locally, different app ):

dev.js:735 Uncaught Error: Hydration Mismatch. Unable to find DOM nodes for hydration key: 1-0-0
    at getNextElement (dev.js:735:13)
    at ErrorBoundary.tsx:32:3
    at ErrorMessage (ErrorBoundary.tsx:59:79)
    at dev.js:616:16
    at untrack (dev.js:499:12)
    at Object.fn (dev.js:612:7)
    at runComputation (dev.js:777:22)
    at updateComputation (dev.js:756:3)
    at devComponent (dev.js:627:3)
    at createComponent (dev.js:1374:17)

I am sure the cause is pretty simple, but I have been programming for hours before I updated and do not have any energy to investigate, just thought I would provide you some validation so you don't spend hours on this.

@ryansolid
Copy link
Member

Ah I see this is a streaming only issue. It's because we client render error boundaries on failure across the suspense boundary. And now that fails hydration ironically as well. Ok.. Let me see what we can do.

@ryansolid ryansolid changed the title Error: Hydration Mismatch. Unable to find DOM nodes for hydration key Streaming ErrorBoundaries where Boundary is flushed before error cause Hydration Mismatch Error Oct 16, 2023
@jules-sommer
Copy link

jules-sommer commented Oct 16, 2023

Ah I see this is a streaming only issue. It's because we client render error boundaries on failure across the suspense boundary. And now that fails hydration ironically as well. Ok.. Let me see what we can do.

Yes, so in my own attempts to keep my app running and development moving forward while waiting to hear on this issue, I did do some investigating and noticed both that renderStream() and SSR ( i.e solid({ ssr: true }) ) were obviously necessary precursors to triggering this error, and I looked into the commits between 1.7.12 and 1.8.1 and found there were changes to the Suspense and ErrorBoundary handling, and I was running under the assumption that it's more likely those changes revealed a bug or strange edge case in my code rather than introduced one in Solid.

But nonetheless I went through my stack trace ( which would frustratingly change every time I saw the error ) and given the transient nature of it, i.e sometimes app runs fine sometimes there's a mismatch, it was particularly annoying to debug.

However, I managed to find a few cases where I maybe wasn't being super safe about hydration where I had dynamic or conditionally rendered components and other control flow fun with an ErrorBoundary or Suspense was involved, and I managed to get it running for now, by just doing this:

<Suspense fallback={<AnotherComponent />}>
  <Show when={isHydrated()}>
    <SomeComponent />
  </Show>
</Suspense>

with a few components that happened to occasionally show up in the stack trace, but again because it doesn't always show up I am not sure if I have just tricked myself into making random changes until it started behaving, especially since those changes were not needed as of 1.7.12.

@ryansolid
Copy link
Member

ryansolid commented Oct 17, 2023

Yeah it is actually a lot simpler than I thought. I was telling the Suspense boundary it had succeeded on server resolve and then it would try to hydrate and fail. ryansolid/dom-expressions@ffeeca4

You shouldn't need those guards this was just a case of errors not being handled properly. Atleast in the reproduction. There could be other things going on. The serializer drives a lot of this now and we implemented a whole new system in 1.8.

I will get this in for the next release.

@ryansolid ryansolid added the bug Something isn't working label Oct 17, 2023
@ryansolid ryansolid reopened this Oct 18, 2023
@ryansolid
Copy link
Member

Seems to be still here. Will look into it more. i had it working in browser probably missed something I modified inline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants