跳至主要內容
版本:11.x

錯誤處理

每當程序中發生錯誤時,tRPC 會回應用戶端一個包含「error」屬性的物件。此屬性包含您在用戶端處理錯誤所需的所有資訊。

以下是因錯誤的請求輸入而產生的範例錯誤回應

json
{
"id": null,
"error": {
"message": "\"password\" must be at least 4 characters",
"code": -32600,
"data": {
"code": "BAD_REQUEST",
"httpStatus": 400,
"stack": "...",
"path": "user.changepassword"
}
}
}
json
{
"id": null,
"error": {
"message": "\"password\" must be at least 4 characters",
"code": -32600,
"data": {
"code": "BAD_REQUEST",
"httpStatus": 400,
"stack": "...",
"path": "user.changepassword"
}
}
}

注意:回傳的堆疊追蹤僅在開發環境中可用。

錯誤碼

tRPC 定義了一系列錯誤碼,每個錯誤碼代表不同類型的錯誤,並以不同的 HTTP 碼回應。

說明HTTP 代碼
BAD_REQUEST由於伺服器認為是客戶端錯誤,因此無法或不會處理請求。400
UNAUTHORIZED由於客戶端請求缺乏針對請求資源的有效驗證憑證,因此尚未完成。401
FORBIDDEN伺服器未經授權存取必要的資料來源,例如 REST API。403
NOT_FOUND伺服器找不到請求的資源。404
TIMEOUT伺服器想要關閉這個未使用的連線。408
CONFLICT伺服器請求資源與目標資源的目前狀態發生衝突。409
PRECONDITION_FAILED已拒絕存取目標資源。412
PAYLOAD_TOO_LARGE請求實體大於伺服器定義的限制。413
METHOD_NOT_SUPPORTED伺服器知道請求方法,但目標資源不支援此方法。405
UNPROCESSABLE_CONTENT伺服器了解請求方法,請求實體也正確,但伺服器無法處理它。422
TOO_MANY_REQUESTS已超過速率限制,或傳送過多請求到伺服器。429
CLIENT_CLOSED_REQUEST已拒絕存取資源。499
INTERNAL_SERVER_ERROR發生未指定的錯誤。500

tRPC 公開一個輔助函式,getHTTPStatusCodeFromError,以協助您從錯誤中擷取 HTTP 代碼

ts
import { getHTTPStatusCodeFromError } from '@trpc/server/http';
 
// Example error you might get if your input validation fails
const error: TRPCError = {
name: 'TRPCError',
code: 'BAD_REQUEST',
message: '"password" must be at least 4 characters',
};
 
if (error instanceof TRPCError) {
const httpCode = getHTTPStatusCodeFromError(error);
console.log(httpCode); // 400
}
ts
import { getHTTPStatusCodeFromError } from '@trpc/server/http';
 
// Example error you might get if your input validation fails
const error: TRPCError = {
name: 'TRPCError',
code: 'BAD_REQUEST',
message: '"password" must be at least 4 characters',
};
 
if (error instanceof TRPCError) {
const httpCode = getHTTPStatusCodeFromError(error);
console.log(httpCode); // 400
}
提示

伺服器端呼叫文件 中有一個完整的範例,說明如何在 Next.js API 端點中使用這項功能。

擲回錯誤

tRPC 提供一個錯誤子類別,TRPCError,您可以使用它來表示在程序中發生的錯誤。

例如,擲回這個錯誤

server.ts
ts
import { initTRPC, TRPCError } from '@trpc/server';
const t = initTRPC.create();
const appRouter = t.router({
hello: t.procedure.query(() => {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'An unexpected error occurred, please try again later.',
// optional: pass the original error to retain stack trace
cause: theError,
});
}),
});
// [...]
server.ts
ts
import { initTRPC, TRPCError } from '@trpc/server';
const t = initTRPC.create();
const appRouter = t.router({
hello: t.procedure.query(() => {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: 'An unexpected error occurred, please try again later.',
// optional: pass the original error to retain stack trace
cause: theError,
});
}),
});
// [...]

會產生下列回應

json
{
"id": null,
"error": {
"message": "An unexpected error occurred, please try again later.",
"code": -32603,
"data": {
"code": "INTERNAL_SERVER_ERROR",
"httpStatus": 500,
"stack": "...",
"path": "hello"
}
}
}
json
{
"id": null,
"error": {
"message": "An unexpected error occurred, please try again later.",
"code": -32603,
"data": {
"code": "INTERNAL_SERVER_ERROR",
"httpStatus": 500,
"stack": "...",
"path": "hello"
}
}
}

處理錯誤

程序中發生的所有錯誤都會在傳送給客戶端之前,先經過 onError 方法。您可以在這裡處理或變更錯誤。

pages/api/trpc/[trpc].ts
ts
export default trpcNext.createNextApiHandler({
// ...
onError(opts) {
const { error, type, path, input, ctx, req } = opts;
console.error('Error:', error);
if (error.code === 'INTERNAL_SERVER_ERROR') {
// send to bug reporting
}
},
});
pages/api/trpc/[trpc].ts
ts
export default trpcNext.createNextApiHandler({
// ...
onError(opts) {
const { error, type, path, input, ctx, req } = opts;
console.error('Error:', error);
if (error.code === 'INTERNAL_SERVER_ERROR') {
// send to bug reporting
}
},
});

onError 參數是一個物件,其中包含所有關於錯誤和它發生時脈絡的資訊

ts
{
error: TRPCError; // the original error
type: 'query' | 'mutation' | 'subscription' | 'unknown';
path: string | undefined; // path of the procedure that was triggered
input: unknown;
ctx: Context | undefined;
req: BaseRequest; // request object
}
ts
{
error: TRPCError; // the original error
type: 'query' | 'mutation' | 'subscription' | 'unknown';
path: string | undefined; // path of the procedure that was triggered
input: unknown;
ctx: Context | undefined;
req: BaseRequest; // request object
}