Neon
Neon2y ago

Throw custom TRPCError with specific cause

Hello everyone ! I'm trying to throw a custom TRPCError with a specific cause that i can differentiate from other trpc errors. My use case is to be able to catch error on client and display an error message if the error code is 'BAD_REQUEST' and a specific cause. After investigating i find that something like this should work in my mutation procedure:

throw new TRPCError({
message: 'Password changed too recently',
code: 'BAD_REQUEST',
cause: { name: 'VALIDATION_ERROR', message: "You can only modify your password once a day" },
});

throw new TRPCError({
message: 'Password changed too recently',
code: 'BAD_REQUEST',
cause: { name: 'VALIDATION_ERROR', message: "You can only modify your password once a day" },
});
But in my errorFormatter i only receive this object
{"code":"BAD_REQUEST","name":"TRPCError"}
{"code":"BAD_REQUEST","name":"TRPCError"}
cause field is not present. Can someone enlighten me on how to solve this problem ? Thanks 🙂
2 Replies
Neon
Neon2y ago
Ok, i find the problem, cause has to be an Error so i replace the code with this:
throw new TRPCError({
message: 'Password changed too recently',
code: 'BAD_REQUEST',
cause: Error("You can only modify your password once a day", { cause: 'VALIDATION_ERROR' }),
});
throw new TRPCError({
message: 'Password changed too recently',
code: 'BAD_REQUEST',
cause: Error("You can only modify your password once a day", { cause: 'VALIDATION_ERROR' }),
});
mellson
mellson14mo ago
I'm experiencing the same thing. If I throw an error on the server, something like this:
throw new TRPCError({
message: 'Hello from a bad request',
code: 'BAD_REQUEST',
cause: 'Custom cause', // get's converted to an Error by getCauseFromUnknown
});
throw new TRPCError({
message: 'Hello from a bad request',
code: 'BAD_REQUEST',
cause: 'Custom cause', // get's converted to an Error by getCauseFromUnknown
});
If I catch the error on the server, the cause is there. But in my errorFormatter, it is no longer present. Is the cause supposed to be present on the client side when using superjson? Ok, it was available in the error formatter when checking the error object. I only checked the shape and the output of the formatter. It seems you need to change the shape to include the cause. Is this intended behavior or some error on my end?
export const t = initTRPC.context<Context>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
// I need to do this to get the cause passed to the client, is this intended?
...(error.cause && {
cause: error.cause.message,
}),
},
};
},
});
export const t = initTRPC.context<Context>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
// I need to do this to get the cause passed to the client, is this intended?
...(error.cause && {
cause: error.cause.message,
}),
},
};
},
});