#useLoaderData returning HTML when express's getLoadContext() throws

1 messages · Page 1 of 1 (latest)

lunar lily
#

Hi - Have a weird one related to the express getLoadContext and useLoaderData.

Now I figure this getLoadContext function should be made quite safe, but I've recently run into a situation where the following appears to happen (intermittently)

  • App is running fine
  • Some error occurs on the express server, which is likely triggering an error when getLoadContext is run (redis timeout/restart issues)
  • getLoadContext throws an error and useLoaderData in the page appears to return the rendered express error page in HTML instead of either the results from its loader (obviously unexpected in that case), or just useLoaderData throwing a JS error itself so nothing else runs.

That behavior is breaking the TypeScript contract of useLoaderData<typeof loader>(), so I'm getting a knock-on error below it.

I'm able to cleanly reproduce this error, so I'll make a reproducible example, but maybe some guidance on how to ensure the getLoadContext is ensured to fail gracefully/cleanly here would be great in case of a problem outside Remix.

As an example, if I threw an error "FOOBAR" in the getLoadContext, useLoaderData is returning

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Error: FOOBAR<br> &nbsp; &nbsp;at ...mycallstack...</pre>
</body>
</html>

For clarity, I'm seeing this in 1.12.0 (where my prod version is running), and I've tested this with the latest 1.14.1-beta.0, same issue.

Thanks for all your help, and keep up the great work!

fleet shore
#

@lunar lily is this loader returning a defer() ?

#

Hm, nevermind.. shouldn't make a difference

lunar lily
#

Hi @fleet shore no this is strictly classic remix rendering

#

Not streaming, etc

fleet shore
#

Yeah that is strange.. I'm running 1.12.0 with express and getLoadContext and can't see that behavior

#

If you have a repro, I'd love to play with it

fleet shore
#

@lunar lily okay, I was able to reproduce it and digged a little bit (was fun)

It basically comes down to this: when a loader/action throws, Remix intercepts and serializes the error in a determined way so the client can render the closest ErrorBoundary. But getLoadContext is called before the remix loader/action handlers, is called inside an express handler

Not sure how easy it would be to pipe this error to the client so the experience is similar, but I believe the new middleware feature would work like that