0Pricing
tRPC End-to-End Type Safe APIs · 课时

优雅地处理 tRPC 错误

在 tRPC 过程和中间件中实现捕获和响应错误的最佳实践。

优雅地处理 tRPC 错误 是 CoddyKit 上的免费 tRPC End-to-End Type Safe APIs 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 tRPC End-to-End Type Safe APIs 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 tRPC End-to-End Type Safe APIs 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

API Errors: A Necessary Evil

In any robust API, errors are inevitable. Users might send invalid data, resources might not exist, or external services could fail.

Implementing graceful error handling is crucial for creating stable and user-friendly applications. It allows your API to respond predictably and informatively.

How tRPC Handles Errors

By default, tRPC automatically catches any JavaScript errors thrown within your procedures or middleware. It serializes them and sends them to the client.

Generic errors are often mapped to an INTERNAL_SERVER_ERROR (HTTP 500) status on the client side if not explicitly handled. Try running this example to see a generic error.

function fetchData(shouldFail: boolean) {
  if (shouldFail) {
    throw new Error("Something went wrong on the server!");
  }
  return "Data fetched successfully.";
}

function main() {
  try {
    console.log("Attempting to fetch (success):");
    console.log(fetchData(false));
  } catch (error: any) {
    // This catch block demonstrates local error handling
    // tRPC server would catch and serialize if not handled here
    console.log(`Caught error: ${error.message}`);
  }

  try {
    console.log("\nAttempting to fetch (fail):");
    fetchData(true);
  } catch (error: any) {
    console.log(`Caught error: ${error.message}`);
  }
}

main();

Standardizing with TRPCError

To provide structured and predictable error responses, tRPC offers the TRPCError class. This is tRPC's dedicated way to throw API-specific errors.

  • TRPCError allows you to specify a code (like an HTTP status) and a human-readable message.
  • It ensures consistent error payloads, making it easier for clients to interpret and react to different error types.

Anatomy of TRPCError

When you create a TRPCError, you pass an object with a code and a message. The code maps to standard HTTP status codes (e.g., NOT_FOUND, UNAUTHORIZED).

This example shows how to throw different TRPCError types based on conditions.

import { TRPCError } from '@trpc/server';

function simulateError(type: string) {
  if (type === 'not_found') {
    throw new TRPCError({
      code: 'NOT_FOUND',
      message: 'Resource does not exist.'
    });
  }
  if (type === 'bad_input') {
    throw new TRPCError({
      code: 'BAD_REQUEST',
      message: 'Invalid input provided.'
    });
  }
  return 'No error was simulated.';
}

function main() {
  try {
    console.log("Simulating 'not_found' error:");
    simulateError('not_found');
  } catch (error: any) {
    if (error instanceof TRPCError) {
      console.log(`TRPC Error Code: ${error.code}`);
      console.log(`TRPC Error Message: ${error.message}`);
    } else {
      console.log(`Generic Error: ${error.message}`);
    }
  }
}

Handling Errors in Procedures

Your tRPC procedures contain the core business logic. It's good practice to wrap operations that might fail (like database calls or API requests) in try...catch blocks.

Inside the catch block, you can translate generic errors into specific TRPCError instances, providing clear feedback to the client.

Example: Procedure Error Handling

This example simulates a procedure trying to fetch a user from a database. It handles both a missing user and a database connection error, converting them into appropriate TRPCError types.

import { TRPCError } from '@trpc/server';

// Simulate a database call
function fetchUserFromDB(id: string) {
  if (id === 'db_error') {
    throw new Error("Database connection failed!");
  }
  if (id === '123') {
    return { id: '123', name: 'Alice' };
  }
  return null;
}

// Simulate a tRPC query procedure
function getUserQuery(userId: string) {
  try {
    const user = fetchUserFromDB(userId);
    if (!user) {
      throw new TRPCError({
        code: 'NOT_FOUND',
        message: 'User not found.'
      });
    }
    return user;
  } catch (error: any) {
    if (error instanceof TRPCError) {
      throw error; // Re-throw tRPC errors directly
    }
    // Catch generic errors and convert them to TRPCError
    throw new TRPCError({
      code: 'INTERNAL_SERVER_ERROR',
      message: `Failed to fetch user: ${error.message}`
    });
  }
}

function main() {
  try {
    console.log("Fetching user '123':");
    console.log(getUserQuery('123'));
  } catch (error: any) {
    console.log(`Error: ${error.code} - ${error.message}`);
  }

  try {
    console.log("\nFetching user 'db_error':");
    getUserQuery('db_error');
  } catch (error: any) {
    console.log(`Error: ${error.code} - ${error.message}`);
  }
}

Error Handling in Middleware

tRPC middleware functions are executed before procedures. They are ideal for global checks like authentication, authorization, or logging.

If a middleware function throws a TRPCError, the procedure it guards will not execute, and the error will be immediately propagated to the client. This is powerful for protecting your API.

Example: Middleware Authorization Error

This middleware checks if the user has an 'admin' role. If not, it throws an UNAUTHORIZED error, preventing any subsequent procedure from running.

This ensures only authorized users can proceed.

import { TRPCError } from '@trpc/server';

// Simulate a tRPC middleware logic
// In a real tRPC app, `ctx` would contain user info
function authMiddleware(userRole: string) {
  if (userRole !== 'admin') {
    throw new TRPCError({
      code: 'UNAUTHORIZED',
      message: 'You are not authorized to perform this action.'
    });
  }
  return { success: true, message: 'Authorized' }; // Simulates `next()`
}

function main() {
  console.log("Attempting with 'user' role:");
  try {
    authMiddleware('user');
  } catch (error: any) {
    if (error instanceof TRPCError) {
      console.log(`Middleware Error: ${error.code} - ${error.message}`);
    }
  }

  console.log("\nAttempting with 'admin' role:");
  try {
    authMiddleware('admin');
    console.log("Middleware passed: User is an admin!");
  } catch (error: any) {
    console.log("This block should not be reached for admin.");
  }
}

main();

Client-Side Error Propagation

When your tRPC server throws a TRPCError, the tRPC client receives a structured error object. This object typically contains:

  • code: The tRPC error code (e.g., 'NOT_FOUND').
  • message: The descriptive error message.
  • data: Additional error data, including the HTTP status code.

This allows your frontend to react specifically to different error types, improving user experience.

Error Handling Check

Consider a tRPC procedure that fetches a blog post. If the user making the request is authenticated but does not have the necessary permissions to view that specific post, what TRPCError code would be most appropriate to throw?

Recap: Graceful Errors

You've learned how to handle errors gracefully in tRPC!

  • tRPC automatically catches generic errors, but TRPCError provides structure.
  • Use TRPCError with specific codes (like NOT_FOUND, UNAUTHORIZED) and messages.
  • Implement try...catch in procedures to convert generic errors into TRPCErrors.
  • Leverage middleware to enforce global checks (e.g., authentication) by throwing TRPCErrors early.
  • Clients receive structured error objects, enabling better frontend error handling.

常见问题解答

「优雅地处理 tRPC 错误」课时是免费的吗?

是的 — 「优雅地处理 tRPC 错误」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 tRPC End-to-End Type Safe APIs 课程的其余内容,请升级到 CoddyKit PRO。 tRPC End-to-End Type Safe APIs 课程共包含 4 节课。

「优雅地处理 tRPC 错误」这节课中我会学到什么?

在 tRPC 过程和中间件中实现捕获和响应错误的最佳实践。 你通过在浏览器中直接运行的动手代码来练习 tRPC End-to-End Type Safe APIs,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 tRPC End-to-End Type Safe APIs 需要有经验吗?

无需任何先前经验。CoddyKit 上的 tRPC End-to-End Type Safe APIs 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「优雅地处理 tRPC 错误」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 tRPC End-to-End Type Safe APIs 课中编写并运行代码吗?

能。每节 tRPC End-to-End Type Safe APIs 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 优雅地处理 tRPC 错误
  2. 自定义错误类型
  3. 用于序列化的数据转换器
  4. 格式化错误与字段级验证反馈
← 返回 tRPC End-to-End Type Safe APIs