-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Closed
Labels
Description
Which project does this relate to?
Start
Describe the bug
Server crashes when there are exceptions in server functions in loader, either middleware or handler itself.
Your Example Website or App
https://github.com/TanStack/router/tree/main/examples/react/start-basic
Steps to Reproduce the Bug or Issue
Add middleware.ts:
import { createMiddleware, json } from "@tanstack/react-start";
export const authMiddleware = createMiddleware({ type: "function" }).server(
async ({ next, context }) => {
throw json({ message: "Unauthorized: missing token" }, { status: 401 });
return next();
}
);
Replace deferred.tsx with following:
import { Await, createFileRoute } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { Suspense, useState } from "react";
import { authMiddleware } from "~/middleware";
const personServerFn = createServerFn({ method: "GET" })
.middleware([authMiddleware])
.inputValidator((d: string) => d)
.handler(({ data: name }) => {
return { name, randomNumber: Math.floor(Math.random() * 100) };
});
const slowServerFn = createServerFn({ method: "GET" })
.inputValidator((d: string) => d)
.handler(async ({ data: name }) => {
await new Promise((r) => setTimeout(r, 1000));
return { name, randomNumber: Math.floor(Math.random() * 100) };
});
export const Route = createFileRoute("/deferred")({
loader: async () => {
return {
deferredStuff: new Promise<string>((r) =>
setTimeout(() => r("Hello deferred!"), 2000)
),
deferredPerson: slowServerFn({ data: "Tanner Linsley" }),
person: await personServerFn({ data: "John Doe" }),
};
},
component: Deferred,
});
function Deferred() {
const [count, setCount] = useState(0);
const { deferredStuff, deferredPerson, person } = Route.useLoaderData();
return (
<div className="p-2">
<div data-testid="regular-person">
{person.name} - {person.randomNumber}
</div>
<Suspense fallback={<div>Loading person...</div>}>
<Await
promise={deferredPerson}
children={(data) => (
<div data-testid="deferred-person">
{data.name} - {data.randomNumber}
</div>
)}
/>
</Suspense>
<Suspense fallback={<div>Loading stuff...</div>}>
<Await
promise={deferredStuff}
children={(data) => <h3 data-testid="deferred-stuff">{data}</h3>}
/>
</Suspense>
<div>Count: {count}</div>
<div>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
</div>
);
}
then go directly to http://localhost:3000/deferred (page needs to be initially loaded from server at that path).
Server crashes with:
Error reading routerStream: g [Error]: The value [object Response] of type "object" cannot be parsed/serialized.
Another way to make it crash:
const personServerFn = createServerFn({ method: "GET" })
.inputValidator((d: string) => d)
.handler(({ data: name }) => {
throw new Error("test");
return { name, randomNumber: Math.floor(Math.random() * 100) };
});
and then remove await in loader:
person: personServerFn({ data: "John Doe" }),
Server crashes with exception:
throw new Error("test");
^
Error: test
Expected behavior
Expect server to never crash due to user's code.
Platform
- Router / Start Version:
"@tanstack/react-start": "^1.132.13",
"@tanstack/react-router": "^1.132.7",
jashwant, eve0415, Crossoufire, PatrickRogg, kvet and 4 more