Skip to main content
Engineering10 min read

尊重用户的错误处理

用户不在乎堆栈跟踪。他们关心哪里出了问题以及下一步该怎么做。以下是我如何设计帮助而非困扰用户的错误体验。

Part ofProduct Systems->
By Jason TeixeiraAugust 25, 2025
Error HandlingUXTypeScriptReactBest Practices
Share:
On this page

大多数错误处理是为已经了解系统的工程师编写的。

这完全是本末倒置。

用户并不关心 Stripe 的 webhook 超时、Supabase 策略拒绝了某行数据,或者模型提供商返回了 429 状态码。他们只关心三件事:

  • 发生了什么
  • 他们的工作是否安全
  • 接下来能做什么

如果界面无法回答这些问题,那么错误信息就没有起到帮助作用,只是在泄露实现细节。

从用户的任务出发,而非异常

错误信息的第一版草稿通常听起来像代码路径:

创建结账会话失败。

这可能是事实,但毫无用处。更好的版本应从用户意图出发:

我们无法打开结账页面。您的项目详情已保存。请重试,或预约电话,我们将手动为您完成。

这条信息完成了四项工作:

  • 说明了失败的操作
  • 确认了数据是否已保存
  • 提供了下一步操作
  • 避免指责用户

内部错误仍然可以记录提供商、状态码、请求 ID 和堆栈跟踪。用户不需要所有这些信息。

将用户文案与工程遥测分离

产品界面和可观测性界面不应承载相同的内容。

尊重用户的错误流程界面 -> 遥测
用户操作错误边界用户文案遥测

用户看到清晰的恢复路径。系统保留堆栈跟踪、请求 ID、提供商响应和告警路由供操作员使用。

在生产环境中,我希望同一个故障产生两个输出:

  • 页面上人类可读的消息
  • 日志、分析和告警中机器可读的事件

用户文案应冷静且具体。遥测数据如果需要可以密集且难看。将这两者混在一起,要么产生无用的日志,要么产生不友好的界面。

良好的错误状态应回答五个问题

当我审查错误状态时,我会用这个清单逐一检查。

如果答案是否定的,那么这个状态还没有完成。

例如,潜在客户表单失败不应显示 500 Internal Server Error。它应该更接近这样的表述:

我们无法发送消息。您的浏览器仍停留在此页面,因此没有丢失任何内容。请重试,或直接通过电子邮件发送项目详情。

然后服务器日志应承载实际原因:验证失败、Resend 超时、Supabase 插入失败或 webhook 拒绝。

在系统故障之前设计降级方案

团队通常是在第一次生产事故后才添加降级状态。这样做代价高昂,因为故障已经公开了。

对于重要的流程,我喜欢在构建功能时就定义降级方案:

流程 用户降级方案 操作员信号
结账 保存路由,提供预约链接 支付提供商错误,附带会话元数据
联系表单 在屏幕上保留消息,显示直接邮箱 潜在客户捕获错误,附带来源和载荷结构
AI 生成 保留提示词,提供重试 提供商、模型、延迟和令牌元数据
文件上传 显示文件限制和重试路径 存储错误、大小、MIME 类型、组织 ID

降级方案不需要花哨。它需要保持用户的进度。

不要让每个错误听起来都一样

通用的消息会让产品显得粗心大意:

  • 出了点问题。
  • 请稍后重试。
  • 发生了意外错误。

有时这些作为最后的兜底信息是可以接受的,但它们不应成为产品中唯一的错误语言。

不同的故障需要不同的恢复路径:

  • 验证错误:显示具体字段和预期格式
  • 权限错误:说明需要什么角色或账户
  • 速率限制:说明何时重试或提供更轻量的操作
  • 依赖故障:保留用户的工作并显示替代路径
  • 破坏性操作失败:明确说明哪些内容没有改变

目标不是让系统看起来完美无缺。目标是在系统不完美时让用户感到有方向感。

操作员需要不同的界面

尊重用户的文案只有在操作员仍然能获得真实证据时才能发挥作用。

这意味着要记录:

  • 路由和操作
  • 请求 ID 或跟踪 ID
  • 用户/组织 ID(如可用)
  • 提供商和状态码
  • 安全的载荷结构
  • 时间信息
  • 重试次数

同时意味着不记录密钥、原始令牌、支付卡详情、私人文档,或可能包含客户数据的完整提示词。

良好的错误处理不是更温和的日志记录,而是更清晰的分离。

我努力交付的模式

对于每个重要操作,我希望实现这样的结构:

  1. 尽早验证并显示字段级别的指导。
  2. 将服务器操作/API 路由包裹在结构化的错误处理中。
  3. 返回稳定的用户消息和稳定的机器代码。
  4. 记录完整的操作员安全上下文。
  5. 如果影响转化率,将故障作为产品事件进行跟踪。
  6. 尽可能保留用户输入。

这不是什么光鲜的工作,但它是高级体验的一部分。能保存你的工作并告诉你下一步该做什么的网站,比那些弹出一个红色框让你重新开始的网站更值得信赖。

Reader route

article -> proof -> offer

ReadClusterProofScope

cluster

Product Systems

intent

Engineering

route

next step

What to do with this

Turn the note into a build path.

If this topic maps to a real business problem, keep reading the cluster, study the academy path, or route the work into a scoped engagement.

Jason Teixeira
Written by
Jason Teixeira
Founder, Sage Ideas Studio · Principal Engineer
livebuild 5d6c8652026-08-05 06:00Z
// solo studio// no analytics resold// every commit human-reviewed