Error handling
面向开发者的 Claude Code skills 套件 | A developer-focused Claude Code skills suite
npx -y skills add Lion-1209/Lion-Skills --skill error-handlingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
设计或改进错误处理与日志时。
SKILL.md
4.9 KB, as published. Nobody here has run it
Error Handling
概述
错误要可观测(知道发生了什么)、可区分(能区分类型)、不吞(不静默 catch)。好的错误处理让你在出问题时能快速定位,而不是对着空白或 undefined 发呆。
何时使用
- 写代码遇到边界/失败场景(空值、超时、外部调用失败),不知怎么处理
- 现有错误处理粗糙(裸 catch、吞异常),要改进
- 设计错误类型/错误码体系
- 决定"这个错该抛还是该处理、要不要重试"
不该用:确定性逻辑(没失败可能,别过度防御)。
核心内容
三态决策:抛 / 处理 / 重试
遇到一个可能的错误,先判断属于哪种:
- 抛(throw / propagate):你处理不了,或属于底层职责。往上传,让上层决策。例:数据库连不上,service 层抛,让调用方决定降级还是报错。
- 处理(handle):你能在原地给出可接受的后续——三种形态:①恢复(用默认值/缓存顶上,如配置缺失用默认配置);②降级(核心功能照跑、非核心跳过,如推荐服务挂了就返回空列表而非整页崩溃);③转成业务语义(把底层异常翻译成业务错误类型抛出,让边界层转成给用户的提示)。业务错误(余额不足、邮箱已注册)归这里——它们不是故障而是预期分支,不重试(结果不会变),抛一个业务错误类型即可。判断"能不能处理"的尺子:**处理后程序能否继续负责任地往下走?**能 → 处理;只是把错藏起来让上层踩坑 → 抛。
- 重试(retry):只对瞬时故障重试——网络抖动、连接超时、HTTP 429/503。指数退避、有上限,耗尽后归为"抛"。三个前提:① 有副作用的调用(支付、下单、写库)重试前必须保证幂等(幂等键或唯一约束),否则重试=重复扣款/重复写入;② 读超时(请求已发出、响应没回来)结果可能已生效,按副作用对待,必须幂等;③ HTTP 429/503 优先遵守响应头
Retry-After。注意 4xx(非 429)和多数 5xx 不是瞬时错误,重试无意义,直接抛。
原则:越靠近错误的层越了解错误含义;但只有能负责任的层才该处理。不知道怎么办就抛上去。
日志
- 记什么:上下文——输入、相关状态、错误对象(含堆栈)
- 敏感信息要脱敏后记,不要完全不记:密码、token、身份证、银行卡——直接丢弃会丢失排查线索("是不是这个用户的请求出问题?")。正确做法是记可识别但不可还原的形式:token 记前 8 位 +
***、手机号记后 4 位、密码只记"是否为空"不记内容。原则:能定位到"是哪个对象/哪次请求",但不能还原出敏感值本身。 - 分级:
debug(排查细节)、info(关键业务节点)、warn(可疑但可继续)、error(出错了需关注)
业务错误 vs 系统错误的日志级别:邮箱已注册、余额不足这类是预期的业务拒绝,不算系统故障——打 info/warn 即可,别打 error 污染告警;DB 连不上、网络失败这类意外故障才打 error。
错误日志要让你光看日志就重现问题现场,而不是只看到 Error: something went wrong。
错误信息面向开发者
错误消息给排查的开发者看,不是给终端用户看:写清发生了什么 + 可能原因 + 怎么排查,并带上下文。
// 差
throw new Error("failed")
// 好
throw new Error(`用户注册失败:邮箱 ${email} 已被注册。检查是否应走登录流程。`)
给用户的提示要另外做(友好、不泄露技术细节),别直接把异常 message 吐给用户。
模式
- 自定义错误类型/错误码:区分业务错误(邮箱已注册)和系统错误(DB 连不上),让上层针对性处理
- fail fast:启动期检查前置条件,不满足直接报错,别带病运行
- 边界统一兜底:在系统边界(HTTP 中间件、API 网关)统一捕获并转换错误,别让内部异常直接漏到外部
- 别 catch 了又原样 throw:要么加上下文再抛,要么处理掉
常见错误
| 问题 | 修法 |
|---|---|
裸 catch(e){} 静默吞错 | 至少记日志 + 决定抛/处理 |
catch 了又 throw e(无添加) | 加上下文再抛,或处理掉 |
日志只记 e.message | 记上下文 + 完整错误对象 |
| 敏感信息要么全记要么全丢 | 脱敏后记(token 记前 8 位 + ***),保留定位能力又不泄露 |
| 把堆栈直接吐给终端用户 | 内部日志详细,给用户友好提示 |
| 不区分错误类型 | 用自定义错误类型/错误码 |
| 无限重试/无退避 | 指数退避 + 最大次数 |