outis99
outis992y ago

Handling errors on the front-end

I'm making a mutation from my front-end and I intentionally throw a new TRPCError on my backend, I can see the trpc error on both client and server console but I don't understand how to catch it in the front-end The mutation onError does nothing, myMutation.isError is false, myMutation.error is null and status "idle" Here's some example code
const sendMessage = api.chatgpt.sendMessage.useMutation({
onError: (error) => {
console.log("error hit", error); //Doesn't execute
setLoadingResponse(false);
},
});
const sendMessage = api.chatgpt.sendMessage.useMutation({
onError: (error) => {
console.log("error hit", error); //Doesn't execute
setLoadingResponse(false);
},
});
And then on my code
sendMessage.mutate({ message: inputRef.current.value, chatId });
sendMessage.mutate({ message: inputRef.current.value, chatId });
How I throw the error
if (result.status === 200) { //Yes 200 is on purpose so I can test it
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "OpenAI API Error",
});
}
if (result.status === 200) { //Yes 200 is on purpose so I can test it
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "OpenAI API Error",
});
}
I also tried this
try {
sendMessage.mutate({ message: inputRef.current.value, chatId });
} catch (cause) {
if (isTRPCClientError(cause)) {
// `cause` is now typed as your router's `TRPCClientError`
// Nothing gets printed
console.log('data', cause.data);

}
}
try {
sendMessage.mutate({ message: inputRef.current.value, chatId });
} catch (cause) {
if (isTRPCClientError(cause)) {
// `cause` is now typed as your router's `TRPCClientError`
// Nothing gets printed
console.log('data', cause.data);

}
}
Pretty sure I'm just missing something here so a little help would be appreciated, thank you!
7 Replies
Nick
Nick2y ago
If it’s not reaching the frontend then most likely your backend isn’t actually throwing the error, or some middleware is swallowing it Check the API-side onError and errorFormatter callbacks are receiving it
outis99
outis99OP2y ago
I can see it on my frontend console
outis99
outis99OP2y ago
Server-side onError receives it as well as the error formatter But as you can see on the image all the error values are false/null I looked through all the files but can't seem to find something that swallows it @nlucas
Nick
Nick2y ago
Okay yeah it’s sending a 500 back so looks like that’s fine It looks like it should be calling the useMutation callback right now To catch imperatively you should await mutateAsync though
outis99
outis99OP2y ago
Even that doesn't work, I'm sorry but I can't see what I am missing here and why throwing an error from the server is so difficult to handle on the client. All of the tRPC settings and files are default and I haven't changed any error formatters or loggerlinks or whatever, should I post a git issue for this maybe?
Dani;
Dani;2y ago
Post your trpc & react-query instantiation code on the client
outis99
outis99OP2y ago
On my _app.tsx export default api.withTRPC(MyApp); The api file
/**
* This is the client-side entrypoint for your tRPC API. It is used to create the `api` object which
* contains the Next.js App-wrapper, as well as your type-safe React Query hooks.
*
* We also create a few inference helpers for input and output types.
*/
import { httpBatchLink, loggerLink } from "@trpc/client";
import { createTRPCNext } from "@trpc/next";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import superjson from "superjson";

import { type AppRouter } from "src/server/api/root";

const getBaseUrl = () => {
if (typeof window !== "undefined") return ""; // browser should use relative url
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url
return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost
};

/** A set of type-safe react-query hooks for your tRPC API. */
export const api = createTRPCNext<AppRouter>({
config() {
return {
/**
* Transformer used for data de-serialization from the server.
*
* @see https://trpc.io/docs/data-transformers
*/
transformer: superjson,

/**
* Links used to determine request flow from client to server.
*
* @see https://trpc.io/docs/links
*/
links: [
httpBatchLink({
url: `${getBaseUrl()}/api/trpc`,
}),
],
};
},
/**
* Whether tRPC should await queries when server rendering pages.
*
* @see https://trpc.io/docs/nextjs#ssr-boolean-default-false
*/
ssr: false,
});

/**
* Inference helper for inputs.
*
* @example type HelloInput = RouterInputs['example']['hello']
*/
export type RouterInputs = inferRouterInputs<AppRouter>;

/**
* Inference helper for outputs.
*
* @example type HelloOutput = RouterOutputs['example']['hello']
*/
export type RouterOutputs = inferRouterOutputs<AppRouter>;
/**
* This is the client-side entrypoint for your tRPC API. It is used to create the `api` object which
* contains the Next.js App-wrapper, as well as your type-safe React Query hooks.
*
* We also create a few inference helpers for input and output types.
*/
import { httpBatchLink, loggerLink } from "@trpc/client";
import { createTRPCNext } from "@trpc/next";
import { type inferRouterInputs, type inferRouterOutputs } from "@trpc/server";
import superjson from "superjson";

import { type AppRouter } from "src/server/api/root";

const getBaseUrl = () => {
if (typeof window !== "undefined") return ""; // browser should use relative url
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url
return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost
};

/** A set of type-safe react-query hooks for your tRPC API. */
export const api = createTRPCNext<AppRouter>({
config() {
return {
/**
* Transformer used for data de-serialization from the server.
*
* @see https://trpc.io/docs/data-transformers
*/
transformer: superjson,

/**
* Links used to determine request flow from client to server.
*
* @see https://trpc.io/docs/links
*/
links: [
httpBatchLink({
url: `${getBaseUrl()}/api/trpc`,
}),
],
};
},
/**
* Whether tRPC should await queries when server rendering pages.
*
* @see https://trpc.io/docs/nextjs#ssr-boolean-default-false
*/
ssr: false,
});

/**
* Inference helper for inputs.
*
* @example type HelloInput = RouterInputs['example']['hello']
*/
export type RouterInputs = inferRouterInputs<AppRouter>;

/**
* Inference helper for outputs.
*
* @example type HelloOutput = RouterOutputs['example']['hello']
*/
export type RouterOutputs = inferRouterOutputs<AppRouter>;
Also previously when I mentioned that settings are default I mean the default t3 stack configuration @s.daniel Let me know if you need anything else