输入校验与错误处理
输入校验
接口在 .input() 中使用 Zod,明确字符串长度、枚举、数量和格式。对外部文件和网址,还需要在处理阶段验证真实内容、响应大小和可访问范围;仅校验后缀或网址格式不够。
ts
import { z } from "zod";
const listInput = z.object({
limit: z.number().int().min(1).max(100).default(20),
});统一错误
apps/api/lib/trpc.ts 为校验错误附加 data.zodError,客户端可把字段错误放回表单。业务错误使用 TRPCError,选择与实际情况一致的类型。
| 错误类型 | 场景 |
|---|---|
BAD_REQUEST | 输入或请求状态不合法 |
UNAUTHORIZED | 缺少有效会话 |
FORBIDDEN | 已登录但无操作权限 |
NOT_FOUND | 资源不存在或不可见 |
CONFLICT | 唯一约束或当前状态冲突 |
INTERNAL_SERVER_ERROR | 未预期的内部失败 |
ts
import { TRPCError } from "@trpc/server";
throw new TRPCError({
code: "FORBIDDEN",
message: "当前账号没有管理权限",
});示例说明错误表达方式;客户站文案按产品语言配置。
前端处理
使用 apps/app/lib/errors.ts 提取状态和可展示消息,区分校验错误、权限错误与网络故障。401 可以引导重新登录;403 应解释权限不足;网络故障保留输入供用户重试。
不要把所有异常改成“没有登录”,也不要在支付失败后自动重试创建订阅。日志保留内部原因和请求标识,响应隐藏堆栈、数据库连接和密钥。
环境错误
启动时 parseEnv() 检查字段组合,诊断只报告错误字段名。先修复缺失变量再重启;不要为了绕过报错把半组凭据补成无效占位值。