1. 为什么一句“出错了”比没提示还可怕刚入行那会儿我参与过一个医疗设备配套软件的维护。某天凌晨三点接到医院电话一台血气分析仪突然无法上传检测结果所有操作都卡在“提交失败”弹窗上——弹窗里只有一行字“Error occurred.” 没有错误码没有时间戳没有模块标识连“重试”按钮都灰掉了。工程师远程连上去查日志发现系统其实早把关键线索写进了后台[2024-03-17T02:48:12.331Z] ERROR [NetworkClient] Failed to POST to /api/v2/results: timeout after 15000ms (host: api-lab-hk.internal)。但前端压根没读这行而是统一扔出那个万能句式。结果我们花了六小时排查DNS配置、证书链、负载均衡健康检查最后才发现是医院新装的防火墙策略把api-lab-hk.internal这个内部域名的DNS查询响应时间拖到了16秒——而客户端超时阈值设死在15秒。这就是模糊错误消息的真实代价它不单是用户体验问题更是故障定位的“信息黑洞”。在真实生产环境里“Error occurred”这种提示相当于给消防员发一张白纸说“火灭了”却不说火在几楼、什么材质烧着、有没有人被困。它让开发者从“调试者”退化成“占卜师”靠猜、靠试、靠重启来推进问题解决。而精准错误消息的本质不是堆砌技术术语而是建立人与系统之间的可信对话通道——告诉用户“发生了什么”现象、“在哪里发生的”上下文、“为什么发生”根本原因、“现在能做什么”可操作建议。它需要同时服务三类角色终端用户需要行动指引、一线支持需要快速分类、开发运维需要根因线索。我后来在团队推行“错误消息四象限法则”左上角写用户能懂的自然语言描述右上角标唯一错误ID如ERR-NET-TIMEOUT-15000左下角放精简技术上下文模块/函数/状态码右下角给具体操作建议“请检查网络连接”或“点击此处刷新认证令牌”。这套结构让客户支持平均首次解决率从38%提升到79%因为支持人员不再需要反复追问“你点哪个按钮时出的错”。精准错误消息也不是越详细越好。我见过一个电商后台系统在支付失败时直接把整个Java异常堆栈原样吐给商户运营人员里面混着数据库连接池密码明文、Redis服务器IP和未脱敏的用户手机号。这已经不是“不精准”而是“危险”。真正的精准是在信息密度与安全边界之间做动态权衡对用户展示必要动作指引对支持提供可分类标签对开发暴露可追溯线索对系统守住敏感数据红线。它背后是一整套工程实践错误分类体系、上下文注入机制、分级日志策略、前端兜底文案库。接下来我们就一层层拆解怎么把“Error occurred”这种废料变成真正能驱动问题解决的燃料。2. 错误消息的底层设计逻辑从“报错”到“对话”的范式转移2.1 为什么传统错误处理总在“堵漏洞”而不是“建桥梁”多数团队处理错误消息的起点是补救式的——某个用户投诉“看不懂提示”PM提需求“改下文案”前端工程师打开代码搜alert(出错了)替换成alert(请求失败请稍后重试)然后提PR合入。这种模式本质是症状治疗把错误消息当成UI文案的子集而非系统可观测性的核心接口。但问题在于错误消息从来不是孤立存在的。它像一根神经末梢一端连着用户操作比如点击“生成报告”按钮一端连着系统最深层的执行路径比如数据库事务回滚、第三方API熔断、内存溢出GC。当这根神经被截断只显示“出错了”整个系统的反馈回路就失效了。我带过的三个不同领域项目金融风控引擎、工业IoT网关、教育SaaS平台都验证过一个规律错误消息质量与MTTR平均修复时间呈强负相关相关系数达-0.87。这不是巧合。当错误消息包含有效上下文时开发人员能跳过50%以上的“复现-确认-定位”循环。比如在IoT网关项目中设备离线告警原本只显示“Connection lost”升级为“[MQTT-CONN-FAIL-003] Device SN:ABC123 failed to reconnect to broker mqtt-prod-east after 3 attempts (last error: Connection refused by broker: port 8883 blocked)”运维人员立刻意识到是防火墙策略变更而不是去查设备固件版本或基站信号强度。这里的关键跃迁是从“错误是需要掩盖的缺陷”转向“错误是系统状态的诚实快照”。2.2 精准错误消息的四大支柱可读性、可追溯性、可操作性、可防御性要支撑这种范式转移必须构建四个不可妥协的支柱。它们不是并列关系而是存在严格的依赖链条没有可读性其他全是空中楼阁没有可追溯性可操作性就是盲人摸象没有可防御性前两者反而成为攻击入口。第一支柱可读性Readability——让非技术人员也能理解发生了什么这不是要求用幼儿园语言而是遵循“用户心智模型优先”原则。比如银行转账失败不要写“Transaction declined due to insufficient funds in source account”而要写“余额不足您的账户还差¥235.60才能完成本次转账”。前者描述系统状态后者描述用户目标受阻的原因。我们团队实测过在200名非技术人员测试中带金额缺口的提示使用户自主解决问题率提升4.3倍从12%到52%。可读性的技术实现要点有三动词驱动永远以用户动作为主语。“您无法保存”优于“保存失败”“文件太大”优于“File size exceeds limit”。单位具象化把技术参数转为生活参照。“图片不能超过5MB”不如“图片不能超过3张高清手机照片大小”。避免否定式表达不写“不支持IE浏览器”而写“请使用Chrome、Firefox或Edge浏览器访问”。第二支柱可追溯性Traceability——让每个错误都有唯一身份证这是精准性的技术基石。没有唯一错误ID所有日志、监控、用户反馈就无法关联。我们采用三级编码体系领域前缀AUTH-认证、PAY-支付、SYNC-同步错误类型TIMEOUT、VALIDATION、NETWORK、PERMISSION实例编号两位数字序列号如01表示该类型首次定义组合起来就是PAY-TIMEOUT-03。这个ID必须贯穿全链路前端展示、后端日志、APM追踪、客服工单系统。当用户反馈“PAY-TIMEOUT-03错误”支持人员输入ID就能调出最近100次该错误的完整调用链、错误分布时段、受影响用户画像。我们曾用这个机制发现PAY-TIMEOUT-03在每天上午9:15-9:25集中爆发最终定位到是财务系统每日结账任务占满数据库连接池。没有这个ID这个问题可能永远被归类为“偶发网络问题”。第三支柱可操作性Actionability——给出明确下一步而不是抛出问题精准错误消息的终极价值是缩短“发现问题”到“执行解决”的距离。它必须回答三个问题我现在能做什么即时操作✅ “点击此处重新登录”✅ “请检查Wi-Fi开关是否开启”❌ “请检查网络配置”用户不知道怎么检查如果不行下一步找谁责任移交✅ “如2小时内仍无法解决请联系技术支持提供错误IDPAY-TIMEOUT-03”这件事会不会影响其他功能影响范围✅ “本次失败不影响您查看历史订单”✅ “您的账户安全未受影响”第四支柱可防御性Defensibility——守住安全与合规底线这是最容易被忽视的致命环节。很多团队把“精准”等同于“信息量大”结果把数据库密码、用户身份证号、内部服务器IP全打在错误页上。我们的防御铁律是任何错误消息输出前必须经过三层过滤敏感词扫描拦截password、secret、key、token、ssn等关键词及其变体如pwd、auth_key上下文脱敏对URL参数、HTTP头、SQL语句自动替换为[REDACTED]权限分级普通用户看到“文件上传失败”管理员看到“文件上传失败/tmp/upload/abc123.tmp 权限不足需755”这四根支柱共同构成精准错误消息的骨架。它们不是文档里的漂亮概念而是每天在代码审查、日志审计、用户反馈中被反复锤炼的工程纪律。下一节我们就进入实操层面看看如何把这套逻辑落地为可运行的代码和流程。3. 实战落地从零搭建精准错误消息体系的七步法3.1 第一步错误分类图谱建设——先画清“错误地图”再填内容所有精准化改造的第一步不是改代码而是绘制组织级错误分类图谱。很多团队跳过这步直接让前端工程师改提示语结果改来改去还是“网络错误”“系统错误”“未知错误”三大类。这就像没画地图就进森林永远在原地打转。我们采用三维分类法覆盖错误的全部维度按触发层级Layer前端交互层如表单校验、应用逻辑层如业务规则冲突、基础设施层如数据库连接超时、第三方依赖层如微信支付回调失败按影响范围Scope用户个人如某订单提交失败、租户隔离如某企业子账号权限异常、全局系统如认证中心宕机按可恢复性Recoverability瞬时可恢复如网络抖动、需人工干预如审核拒绝、需系统修复如代码缺陷这张图谱不是静态文档而是活的决策树。例如当一个错误同时属于“基础设施层全局系统需系统修复”它必须触发P0级告警并自动创建Jira工单如果是“前端交互层用户个人瞬时可恢复”则前端应自动重试3次失败后才显示友好提示。我们用Excel维护这张图谱但关键在字段设计错误ID触发层级影响范围可恢复性用户提示文案支持人员指引开发定位线索是否记录全量日志AUTH-VALIDATE-01应用逻辑层用户个人瞬时可恢复“手机号格式不正确请输入11位数字”检查前端正则表达式/^1[3-9]\d{9}$/AuthController.validatePhone()方法第42行否这张表每周由Tech Lead、Support Lead、QA Lead三方评审更新。它让错误处理从“凭经验猜测”变成“按图索骥”。比如新来的实习生遇到PAY-VALIDATE-02错误不用问任何人查表就知道该看支付网关的金额校验逻辑且知道前端提示应该写“单笔支付不能超过¥50,000”。3.2 第二步错误ID生成与注入——让每个错误自带“出生证明”有了分类图谱下一步是确保每个错误实例都携带合法ID。我们放弃手动生成ID易错、难维护采用编译期注入运行时增强双保险方案。前端React为例// utils/errorHandler.ts export const createError ( baseId: string, // 如 PAY-TIMEOUT context?: { orderId?: string; userId?: string; timestamp?: number; } ) { // 自动生成唯一实例ID基础ID 时间戳哈希 随机数 const instanceId ${baseId}-${Date.now().toString(36).slice(-4)}-${Math.random().toString(36).substr(2, 3)}; return { id: instanceId, message: getReadableMessage(baseId), // 从i18n资源库读取 context: { ...context, instanceId, // 确保上下文里也带ID userAgent: navigator.userAgent, url: window.location.href } }; }; // 使用示例 try { await api.submitPayment(order); } catch (err) { const error createError(PAY-TIMEOUT, { orderId: ORD-2024-789 }); logErrorToSentry(error); // Sentry自动捕获instanceId showUserToast(error.message); // 显示用户友好提示 }后端Node.js Express// middleware/errorHandler.js const generateErrorId (baseId) { const now Date.now(); // 使用CRC32生成短哈希避免长字符串污染日志 const hash crc32(${baseId}-${now}-${process.pid}).toString(36).slice(0, 5); return ${baseId}-${hash}-${now % 1000}; }; app.use((err, req, res, next) { const errorId generateErrorId(err.baseId || UNKNOWN); // 注入到响应头供前端读取 res.setHeader(X-Error-ID, errorId); // 记录结构化日志JSON格式 logger.error({ errorId, baseId: err.baseId, timestamp: new Date().toISOString(), method: req.method, path: req.path, userId: req.user?.id || ANONYMOUS, ip: getClientIp(req), stack: err.stack // 仅开发环境记录完整堆栈 }); // 返回标准化错误响应 res.status(err.statusCode || 500).json({ error: { id: errorId, message: getErrorMessage(err.baseId, req.locale), code: err.statusCode || 500 } }); });这个方案的关键优势在于一致性前后端ID生成规则统一便于全链路追踪低侵入业务代码只需调用createError(PAY-TIMEOUT)无需关心ID生成细节可审计所有错误ID都带时间戳和进程ID杜绝重复或伪造提示我们禁用UUID作为错误ID因为a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8这种字符串对人类完全不友好客服人员无法口头传达用户截图也难以辨认。短哈希时间戳组合在可读性和唯一性间取得平衡。3.3 第三步用户提示文案库建设——不是写文案而是设计“对话脚本”精准错误消息的文案不是UI设计师的自由发挥而是基于用户旅程的对话脚本设计。我们把每个错误ID对应一个文案对象包含四个必填字段{ id: SYNC-CONFLICT-01, userMessage: 检测到数据冲突您编辑的客户资料与服务器最新版本不一致, actionButtons: [ { text: 加载服务器版本, type: load-server, tooltip: 放弃本地修改获取最新数据 }, { text: 保留我的修改, type: keep-local, tooltip: 覆盖服务器数据需二次确认 } ], supportLink: /help/sync-conflict, severity: warning }这个结构强制文案具备可操作性。actionButtons数组确保每个错误都提供至少一个明确动作而不是让用户干瞪眼。tooltip字段在悬停时显示技术含义满足高级用户需求又不干扰普通用户。文案库的维护流程极其严格新增错误ID时必须由产品、前端、后端、客服四方会签文案文案修改时A/B测试至少2000名用户衡量“首次解决率”和“客服咨询量”变化每季度审计删除半年内零触发的错误文案合并相似ID如AUTH-LOGIN-01和AUTH-LOGIN-02都指密码错误则合并为AUTH-LOGIN-01我们曾因一个文案改动节省百万成本旧版AUTH-PERMISSION-02提示是“无权访问此页面”新版改为“您当前角色销售专员无权查看财务报表。如需权限请联系管理员张经理ext. 8021”。结果该错误导致的客服电话量下降63%因为用户直接按提示找到责任人而不是打客服热线问“我为什么看不到”。3.4 第四步日志与监控联动——让错误消息成为可观测性引擎的燃料精准错误消息的价值80%体现在日志和监控系统中。我们构建了“错误ID驱动”的可观测性闭环日志层所有服务日志必须包含error_id字段。ELK Stack中配置专用解析器%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} \[%{DATA:service}\] %{DATA:error_id} %{GREEDYDATA:message}这样在Kibana中可直接用error_id: PAY-TIMEOUT-03筛选全链路日志无需grep关键词。监控层Prometheus采集错误ID计数指标# 每分钟各错误ID出现次数 rate(app_error_total{jobpayment-service}[1m])Grafana面板设置智能告警当PAY-TIMEOUT-03的rate突增300%且持续5分钟自动触发告警并在告警消息中嵌入最近3次错误的完整上下文用户ID、订单号、时间戳。APM层Jaeger/Zipkin中每个Span必须标注error.id标签。当用户报告SYNC-CONFLICT-01运维可直接在APM中搜索该ID看到完整的调用链Frontend → API Gateway → Auth Service → Payment Service → Database ↑ error.idSYNC-CONFLICT-01 on Payment Service Span并立即定位到是Payment Service调用数据库时返回了CONFLICT状态码而非网关或前端的问题。这个联动机制让错误消息从“被动提示”升级为“主动诊断线索”。一次线上事故中我们通过AUTH-TOKEN-EXPIRED-01错误ID的突增5分钟内定位到是新上线的JWT密钥轮换脚本未同步到所有节点避免了更大范围的用户登录失败。3.5 第五步前端兜底与渐进增强——在不可靠网络中守护用户体验真实世界里网络不可靠、CDN缓存异常、JS加载失败都是常态。我们绝不假设错误消息一定能从后端拿到而是构建三层兜底机制第一层编译时静态文案Webpack构建时将文案库JSON打包进前端Bundle确保即使API完全不可用也能显示基础提示// build-time generated const STATIC_ERROR_MESSAGES { PAY-TIMEOUT-03: 支付请求超时请检查网络后重试, AUTH-VALIDATE-01: 手机号格式不正确 };第二层Service Worker缓存注册Service Worker缓存最近100个错误ID的最新文案self.addEventListener(fetch, event { if (event.request.url.includes(/api/errors/)) { event.respondWith( caches.match(event.request) .then(response response || fetch(event.request)) .then(response { if (response.ok) { caches.open(error-messages).then(cache cache.put(event.request, response)); } return response; }) ); } });第三层智能降级当所有兜底失效时启用“最小可行提示”const fallbackMessage (errorId) { const layer errorId.split(-)[0]; // AUTH, PAY, SYNC switch(layer) { case AUTH: return 账户相关操作失败; case PAY: return 支付过程出现问题; case SYNC: return 数据同步未完成; default: return 操作未能成功; } };这三层机制保障了即使后端服务雪崩、CDN全挂、用户网络只剩2G用户依然能看到有意义的提示而不是空白页或“undefined”。我们在东南亚市场实测该方案将弱网环境下的用户留存率提升了22%。3.6 第六步客服与支持系统集成——让错误ID成为跨部门协作的通用语言精准错误消息的最大价值往往在客服环节释放。我们打通了错误ID与客服系统的全链路用户端所有错误弹窗右下角固定显示小字“错误IDPAY-TIMEOUT-03”并提供一键复制按钮客服端Zendesk工单系统接入错误ID解析插件输入ID自动展开最近10次该错误的完整日志摘要受影响用户地域分布热力图关联的已知问题Confluence知识库链接自动推荐解决方案如“92%的PAY-TIMEOUT-03案例可通过刷新页面解决”知识库Confluence中每个错误ID对应独立页面包含用户可见提示文案技术根因说明含代码片段已验证的解决步骤分用户/客服/开发三栏历史修复记录谁、何时、如何修复这个集成让客服从“传声筒”变成“问题终结者”。以前客服接到AUTH-LOGIN-02多因素认证失败投诉要花5分钟问用户“您点的哪个按钮”“看到什么文字”现在用户直接发ID客服点开页面看到“该错误98%因Google Authenticator时间偏差超过30秒导致”立即指导用户校准手机时间平均处理时长从8.2分钟降至47秒。3.7 第七步持续演进机制——把错误消息当作产品来迭代最后一步也是最关键的一步建立错误消息的PDCA循环。我们每月进行“错误消息健康度评审”指标计算方式健康阈值行动项ID覆盖率使用错误ID的错误场景数 / 总错误场景数≥95%对未覆盖场景补充ID定义用户求助率含某错误ID的客服工单数 / 该错误ID总触发次数≤5%文案优化或增加自助解决方案MTTR关联度使用错误ID定位根因的平均耗时 / 不使用ID的平均耗时≤30%优化日志上下文注入点文案陈旧率超过6个月未更新的错误文案数 / 总文案数≤10%清理或重构过时文案评审会由CTO亲自主持强制要求每个错误ID必须有明确负责人Owner每次评审必须关闭至少3个待办如“优化SYNC-CONFLICT-01文案”所有改进必须在两周内上线验证这个机制让错误消息体系持续进化。一年下来我们淘汰了23个冗余ID合并了17个相似ID新增了8个高频新错误ID如AI-GEN-QUOTA-01整体错误处理效率提升3.8倍。4. 血泪教训那些年我们踩过的精准错误消息大坑4.1 坑一把“精准”误解为“信息量爆炸”结果制造新的认知负担刚推行精准错误消息时我们犯过最典型的错误追求“技术完整性”把所有能挖的信息全塞进提示框。一个数据库连接失败的提示曾经长得像这样错误ID: DB-CONN-FAIL-01详情: Connection refused to postgresql://prod-db-01.internal:5432/myapp?sslmoderequire (ECONNREFUSED)上下文: Node.js v18.17.0, pg8.11.0, process.uptime()14283s, memory.rss1.2GB建议: 检查数据库服务状态、SSL证书有效期、连接池配置max20、idleTimeoutMillis30000用户看到这个第一反应是截图发给朋友问“这啥意思”。我们花了整整两周做用户访谈才明白问题所在精准不等于堆砌而是聚焦用户此刻最需要的信息。真正的解决方案是“分层披露”默认视图95%用户看到“服务暂时不可用我们正在紧急修复数据库连接问题。预计10分钟内恢复。”展开视图点击“查看详情”“技术状态数据库集群prod-db-01连接拒绝错误IDDB-CONN-FAIL-01。当前影响所有数据查询与写入。”开发者视图控制台快捷键CtrlShiftE完整堆栈、连接字符串脱敏版、实时监控图表链接这个分层设计让普通用户获得安心感技术支持获得关键线索开发人员获得调试入口。上线后该错误的用户咨询量下降89%因为95%的人看到第一行就明白了“不是我的问题等等就好”。4.2 坑二错误ID生成缺乏规范导致全链路追踪彻底失效有次重大故障用户报告AUTH-TOKEN-EXPIRED-01错误激增。我们按ID查日志却发现前端上报的ID是AUTH-TOKEN-EXPIRED-01-abc123后端日志里是AUTH-TOKEN-EXPIRED-01-20240317-45678APM链路中是auth_token_expired_01_v2三个ID长得像亲戚但完全无法关联。排查了8小时才发现前端工程师自己写了随机ID生成器后端用时间戳哈希APM团队又按自己规则重命名。错误ID失去了“唯一身份证”的意义变成一堆乱码。血的教训让我们制定ID生成铁律唯一来源所有ID必须由中央服务如error-id-service统一分发禁止各端自行生成格式强制{DOMAIN}-{TYPE}-{VERSION}如AUTH-TOKEN-EXPIRED-v1版本号随语义变更递增传输强制ID必须通过HTTP HeaderX-Error-ID传递禁止放在Query String或Body中易被日志系统截断实施后全链路追踪成功率从42%提升至99.7%。现在一个ID就能串起从用户点击到数据库慢查询的完整路径。4.3 坑三忽略国际化场景让精准变成“精准的混乱”我们拓展日本市场时以为把文案库翻译成日语就万事大吉。结果发现日语用户看到PAY-TIMEOUT-03提示“支払いリクエストがタイムアウトしました支払いリクエストがタイムアウトしました”后面括号里重复了相同内容原因是英文文案Payment request timed out (Payment request timed out)被直译而日语习惯用更简洁的“支払いリクエストがタイムアウトしました”更严重的是时区问题错误ID中的时间戳用UTC但日本客服看日志时习惯用JST导致他们以为错误发生在“明天”。解决方案是国际化专项治理文案审核所有翻译必须由母语者领域专家双签重点检查是否符合当地表达习惯如德语偏好名词化英语偏好动词化数字/货币/日期格式是否本地化¥235.60vs235,60 ¥ID去时区化错误ID中移除时间戳改用单调递增序列号如PAY-TIMEOUT-03-00012345时间信息只存在日志中上下文本地化context对象中增加locale字段确保日志分析时能按区域聚合这个治理让日本市场用户投诉率下降76%因为提示终于像“人话”了。4.4 坑四过度依赖自动化忘了错误消息是“人机协作”的产物有次我们上线AI驱动的错误文案生成器用LLM根据错误堆栈自动生成用户提示。效果惊人DB-QUERY-FAILED-02查询超时的提示从“数据库查询失败”变成“检测到复杂报表查询耗时过长当前12.4秒超阈值10秒建议①缩小时间范围 ②减少筛选条件 ③联系管理员优化索引”。但很快收到大量投诉用户说“我根本不会优化索引这提示对我没用”。原来AI生成的提示完美服务于DBA却忽略了终端用户——一个只会点“导出Excel”的销售助理。我们立刻叫停AI生成回归“人本设计”用户角色映射表每个错误ID绑定目标用户角色如DB-QUERY-FAILED-02→sales-assistant,finance-analyst,dba角色专属文案同一错误销售助理看到“报表生成需要更长时间建议先查看今日数据”DBA看到“查询执行计划显示全表扫描建议添加复合索引...”A/B测试验证每次文案更新必须对目标角色用户群做A/B测试核心指标是“自助解决率”而非“技术准确率”这个调整让错误消息真正回到服务人的初心。毕竟精准的终极标准不是技术人觉得多准确而是用户觉得多有用。4.5 坑五安全防御流于形式让错误消息成为攻击者的探针最惊险的一次是渗透测试团队发现我们的AUTH-VALIDATE-01手机号校验失败错误在开发环境会返回完整正则表达式/^1[3-9]\d{9}$/而生产环境只返回“格式不正确”。攻击者利用这点通过反复提交不同格式的手机号反推出我们实际使用的正则进而构造绕过校验的恶意输入。这暴露了安全防御的最大误区把脱敏当成一次性动作而不是贯穿全生命周期的流程。我们重建了“错误消息安全流水线”开发阶段ESLint插件eslint-plugin-security扫描禁止在错误消息中拼接变量如Invalid phone: phone测试阶段自动化测试用Burp Suite扫描所有错误响应检测敏感信息泄露发布阶段CI/CD流水线插入error-scan步骤对打包后的错误文案JSON做正则匹配/password|secret|key|token|ssn/i运行阶段WAF规则拦截含敏感词的错误响应自动替换为泛化提示这套流水线让错误消息安全从“事后补救”变成“事前免疫”。上线半年0次因错误消息导致的安全事件。5. 经验沉淀精准错误消息的12条实战军规5.1 军规一错误ID必须像身份证一样唯一、稳定、可读唯一同一错误场景无论何时何地触发ID必须相同如PAY-TIMEOUT-03稳定ID一旦发布永不更改语义变更则升版PAY-TIMEOUT-04可读禁用UUID采用DOMAIN-TYPE-SEQ格式如AUTH-LOGIN-01长度≤15字符5.2 军规二用户提示永远回答“我现在该怎么办”删除所有被动语态“提交失败”→“您尚未提交成功”每个提示必须含一个动词“点击”“检查”“联系”“等待”禁用“请”字开头“请检查网络”→“检查网络连接”降低心理压迫感5.3 军规三上下文注入必须“恰到好处”不多不少必须注入错误ID、时间戳ISO8601、用户ID脱敏、请求路径禁止注入原始密码、密钥、完整堆栈、数据库连接字符串推荐注入设备类型mobile/web、网络类型4G/WiFi、地理位置城市级5.4 军规四日志与监控必须“错误ID先行”所有日志行必须以error_id开头如error_idPAY-TIMEOUT-03 levelERROR ...Prometheus指标必须含error_id标签app_error_total