mit einem Klick
error-handling
处理错误与异常时使用。不吞异常、不裸抛、给出可恢复信息。
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Menü
处理错误与异常时使用。不吞异常、不裸抛、给出可恢复信息。
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Basierend auf der SOC-Berufsklassifikation
做 Cocos Creator 多机型/多分辨率适配时使用。Canvas、Widget、安全区。
Cocos Creator 用 AssetBundle 做分包/远程资源时使用。加载、释放、依赖、缓存。
优化 Cocos Creator 渲染性能时使用。合批、图集、动静分离、Label。
给 Cocos Creator 原生包做热更新时使用。version manifest、增量、校验、回滚。
写 Cocos Creator 动效/动画时使用。tween、Animation、Spine、性能与清理。
做 Cocos Creator 大量条目列表时使用。虚拟列表、节点复用。
| name | error-handling |
| description | 处理错误与异常时使用。不吞异常、不裸抛、给出可恢复信息。 |
| category | backend |
| tags | ["错误处理","异常"] |
console.log(e) 时。规则: catch/except 块里必须有真正的处理动作——记录日志、触发回滚、重新抛出或转换为业务错误;禁止空 catch 块,禁止仅打印后继续正常流程假装没发生过。
为什么: AI 生成代码时,"先写个 try-catch 让它跑起来"是最常见的反模式——catch (e) {} 或 except: pass。空 catch 会把真实的数据库连接失败、磁盘写入错误、第三方 API 超时全部静默吞掉,函数返回"成功",上层完全感知不到异常,日志里没有任何线索,用户看到的是数据没有保存但页面显示"操作成功"。定位这类 bug 通常要花几倍时间,因为所有的证据都被主动销毁了。
怎么做:
throw/raise),让上层决定。throw new PaymentFailedException("支付网关超时", cause=e)。finally 块做资源清理,不要把清理逻辑写在 catch 里然后 return 提前跳出。规则: 明确区分两类错误——可预期的业务错误(用户输入非法、资源不存在、权限不足)和意外的系统错误(空指针、数据库宕机、bug);前者用业务异常类表达,后者进入全局 handler 并触发告警。
为什么: AI 生成的代码经常把所有异常一律 catch (Exception e) 然后返回 500——校验失败返回 500、资源不存在返回 500、真正的 bug 也是 500。监控告警全是噪音,用户看到的错误信息毫无意义,oncall 工程师不知道哪些 500 需要紧急处理、哪些是正常的业务错误被错误分类了。错误分类是可观测性的基础,混在一起会让整个告警体系失效。
怎么做:
# 业务异常基类(可预期,映射到 4xx)
class AppError(Exception):
def __init__(self, code: str, message: str, http_status: int = 400):
self.code = code
self.message = message
self.http_status = http_status
class ResourceNotFoundError(AppError):
def __init__(self, resource: str, resource_id):
super().__init__("RESOURCE_NOT_FOUND", f"{resource} {resource_id} 不存在", 404)
# 意外错误不捕获,让全局 handler 接管,触发告警
def get_user(user_id: int) -> User:
user = db.query(User).get(user_id)
if user is None:
raise ResourceNotFoundError("User", user_id) # ✅ 业务错误,明确分类
return user
规则: 错误日志必须包含"哪个操作、哪个输入、在哪一步失败"的上下文;但对外返回的错误信息不能包含数据库表名、SQL 语句、堆栈、密钥、用户密码等敏感内容。
为什么: AI 有两种相反的倾向:要么日志只有 "操作失败" 一句话,查问题像盲人摸象;要么直接把框架抛出的原始异常(含 SQL 语句、文件路径、变量值)直接序列化返回给前端,攻击者可以从中提取数据库结构、推断内部逻辑。两种极端都在真实生产事故中反复出现。
怎么做:
logger.error("创建订单失败 user_id=%s product_id=%s amount=%s", uid, pid, amt, exc_info=True) — 带参数、带堆栈。{"code": "ORDER_CREATE_FAILED", "message": "订单创建失败,请稍后重试"} — 友好文案,无内部细节。DEBUG=False、NODE_ENV=production),避免默认暴露堆栈。1380***8888)。规则: 操作失败时必须清理已完成的副作用:回滚数据库事务、删除已创建的临时文件、释放已获取的锁、取消已发出的可撤销请求;不能让系统停留在"一半成功一半失败"的中间状态。
为什么: AI 在处理多步操作时极容易只写成功路径:第一步写数据库成功,第二步发消息失败,然后 catch 里只打了一行日志——数据库里有了这条记录,但消息没发出去,系统进入不一致状态。这类 bug 不会立刻报错,会在后续的业务流程里以奇怪的方式暴露(重复处理、数据对不上),且很难复现和修复。
怎么做:
with/using/RAII 模式,保证无论正常还是异常路径都会释放:# ✅ 正例:即使中途抛异常,文件也会被关闭
with open("report.csv", "w") as f:
write_report(f) # 若此处抛异常,with 保证 f.close() 被调用
# ❌ 反例:异常发生后 f.close() 不会执行,文件句柄泄漏
f = open("report.csv", "w")
write_report(f)
f.close()
规则: 在应用最外层(HTTP 中间件、消息消费入口、定时任务入口)设置全局异常 handler,统一兜住所有漏网异常;对用户返回固定的友好提示,同时保证完整的错误信息(含堆栈)被记录到日志系统。
为什么: AI 生成的服务代码经常没有全局兜底——未处理的异常直接导致 Node.js 进程崩溃、Python Flask 返回裸 HTML 500 页面、Go 的 panic 泄露 goroutine 堆栈给客户端。每加一个新接口都需要记住加 try-catch,一旦有人忘了,对外就是 500 裸崩。设置全局兜底等于给整个系统加了安全气囊,不依赖每个开发者都记得处理所有异常。
怎么做:
# FastAPI 全局异常处理示例
from fastapi import Request
from fastapi.responses import JSONResponse
@app.exception_handler(AppError)
async def app_error_handler(request: Request, exc: AppError):
# 业务错误:记录 warn,返回 4xx
logger.warning("业务错误 path=%s code=%s", request.url.path, exc.code)
return JSONResponse(status_code=exc.http_status,
content={"code": exc.code, "message": exc.message})
@app.exception_handler(Exception)
async def unhandled_error_handler(request: Request, exc: Exception):
# 意外错误:记录 error + 完整堆栈,触发告警,返回 500
logger.error("未捕获异常 path=%s", request.url.path, exc_info=True)
alert_oncall(exc) # 触发告警
return JSONResponse(status_code=500,
content={"code": "INTERNAL_ERROR", "message": "服务暂时异常,请稍后重试"})
# 反例 — 吞掉了数据库异常,函数返回 None 假装成功
def save_order(order: Order) -> bool:
try:
db.session.add(order)
db.session.commit()
return True
except Exception:
pass # ❌ 什么都没做:日志没有,回滚没有,调用方不知道失败了
return False # 调用方收到 False 但不知道是哪类错误,也没法重试
# 调用方
if not save_order(order):
print("保存失败") # ❌ 但没有任何错误信息可以定位问题
# 正例 — 明确回滚 + 记录 + 重抛
def save_order(order: Order) -> None:
try:
db.session.add(order)
db.session.commit()
except SQLAlchemyError as e:
db.session.rollback() # ✅ 清理:回滚事务
logger.error("保存订单失败 order_id=%s", order.id, exc_info=True) # ✅ 记录完整堆栈
raise OrderPersistenceError("订单保存失败") from e # ✅ 转换语义后重抛
# 反例 — 内部 SQL 错误暴露给客户端
@app.route("/users/<int:user_id>")
def get_user(user_id):
try:
return jsonify(db.get_user(user_id))
except Exception as e:
return jsonify({"error": str(e)}), 500
# ❌ str(e) 可能包含:
# "column 'passwrd' does not exist in table 'users'"
# 暴露了表名、字段名,攻击者可以利用这些信息
# 正例 — 内外信息分离
@app.route("/users/<int:user_id>")
def get_user(user_id):
try:
return jsonify(db.get_user(user_id))
except ResourceNotFoundError as e:
return jsonify({"code": e.code, "message": e.message}), 404 # ✅ 业务错误,友好提示
except Exception as e:
logger.error("获取用户失败 user_id=%s", user_id, exc_info=True) # ✅ 完整堆栈写日志
return jsonify({"code": "INTERNAL_ERROR", "message": "服务异常"}), 500 # ✅ 对外不暴露细节
with/using/RAII 模式管理,异常路径也能保证释放。