-
|
I want to check whether the user has access to a specific page or not. Inside the errorComponent, I want to detect whether the error is that specific custom error, and if so, display the error message along with the permissions the user is missing. But TanStack Start's behavior feels a bit weird here. During SSR everything works fine and the error data is available correctly. Sample : src/routes/error.tsx: import { createFileRoute } from "@tanstack/react-router";
export class ForbiddenError extends Error {
public missedPermissions: string[];
constructor(
message: string,
missedPermissions: string[],
opts?: { cause: unknown },
) {
super(message, opts);
this.missedPermissions = missedPermissions;
this.name = "ForbiddenError";
}
}
export const Route = createFileRoute("/error")({
beforeLoad: () => {
throw new ForbiddenError("403 - Forbbiden", ["A", "B", "C"]);
},
component: RouteComponent,
});
function RouteComponent() {
return <div>Hello "/error"!</div>;
}src/router.tsx: import { createRouter as createTanStackRouter } from "@tanstack/react-router";
import { routeTree } from "./routeTree.gen";
export function getRouter() {
const router = createTanStackRouter({
routeTree,
scrollRestoration: true,
defaultPreload: "intent",
defaultPreloadStaleTime: 0,
defaultErrorComponent: ({ error }) => (
<pre>{JSON.stringify(error, null, 2)}</pre>
),
});
return router;
}
declare module "@tanstack/react-router" {
interface Register {
router: ReturnType<typeof getRouter>;
}
}run and navigate to : |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
|
This is a serialization issue. When Two approaches: 1. Use Instead of a custom class, attach your data to a regular Error via a serializable property: beforeLoad: () => {
const error = new Error("403 - Forbidden");
(error as any).data = {
type: "ForbiddenError",
missedPermissions: ["A", "B", "C"],
};
throw error;
},Then in errorComponent: defaultErrorComponent: ({ error }) => {
const data = (error as any).data;
if (data?.type === "ForbiddenError") {
return <div>Missing: {data.missedPermissions.join(", ")}</div>;
}
return <pre>{error.message}</pre>;
},2. Use If this is an auth concern, beforeLoad: () => {
throw redirect({
to: "/forbidden",
search: { missing: ["A", "B", "C"] },
});
},Does the first approach preserve your data on the client side? |
Beta Was this translation helpful? Give feedback.
This is a serialization issue. When
beforeLoadthrows your customForbiddenError, TanStack Router serializes it to send from server to client during hydration. Custom class instances don't survive that serialization — you get a plainErroron the client side, andmissedPermissionsis gone.Two approaches:
1. Use
dataon a plain Error (simplest)Instead of a custom class, attach your data to a regular Error via a serializable property:
Then in errorComponent: