
我们有个支付回调服务逻辑不复杂——接收第三方支付结果校验签名更新订单状态发个通知。这代码跑了两年没出过事直到上个月我决定让AI帮我重写异常处理部分。起因是代码里的try-catch太随意了到处都是catch(Exception e)然后log.error完事有些异常该重试的没重试该回滚的没回滚。我把代码丢给AI让它帮我规范化异常处理它倒是挺积极一口气给我加了七八种异常类型和对应的处理策略。改完上线当天下午就出事了。一笔支付回调处理到一半下游通知服务超时AI加的代码把异常吞了——它在我的NotificationService调用外面包了一层catch捕获了RpcException之后只打了个warn日志然后继续往下走返回了处理成功。结果是订单状态改了但用户没收到通知客服电话被打爆了。AI到底改了什么原来的代码大概是这样java public void handleCallback(PayCallbackRequest request) { try { verifySignature(request); orderService.updateStatus(request.getOrderId(), PAID); notificationService.notify(request.getOrderId()); } catch (Exception e) { log.error(支付回调处理失败, orderId{}, request.getOrderId(), e); throw e; } }丑是丑了点但至少有个底线——出了异常就往上抛调用方知道失败了会走重试逻辑。AI改成了这样java public void handleCallback(PayCallbackRequest request) { try { verifySignature(request); } catch (SignatureException e) { log.warn(签名校验失败, orderId{}, request.getOrderId()); return; // 签名失败直接返回合理 }try { orderService.updateStatus(request.getOrderId(), PAID); } catch (OrderUpdateException e) { log.error(订单状态更新失败, orderId{}, request.getOrderId(), e); throw e; // 订单更新失败要抛合理 } try { notificationService.notify(request.getOrderId()); } catch (RpcException e) { log.warn(通知服务调用失败, orderId{}, request.getOrderId(), e); // 通知失败不影响主流程 —— AI的注释 }} 乍一看挺合理的对吧签名失败直接返回、订单更新失败抛异常、通知失败不影响主流程——这个分层处理思路没错。但AI忽略了一个关键的业务约束我们的支付回调接口返回success之后第三方就不会再重试了。通知失败这条路径原本依赖的是整个方法抛异常 → 调用方返回fail → 第三方重试回调 → 通知再次触发。AI把异常吞了等于把重试链路掐断了。排查过程这个问题排查了将近两小时。客服反馈用户没收到支付成功通知我去查订单状态——已支付没毛病。再查通知记录——空。看日志只有一条warn通知服务调用失败。AI加的那个catch把异常吃掉了调用方以为处理成功了返回了success给第三方。最气人的是AI还在catch里加了注释——通知失败不影响主流程。这话在技术层面没错但它不考虑业务层面对于支付回调来说通知是必须要送达的不是可选项。怎么修的分两步走。第一步通知失败不能吞异常但也不能阻塞主流程。我改成异步重试java try { notificationService.notify(request.getOrderId()); } catch (RpcException e) { log.warn(通知服务调用失败, orderId{}, 进入重试队列, request.getOrderId()); retryQueue.add(new NotifyRetryTask(request.getOrderId())); // 不抛异常但保证通知最终会送达 }第二步给重试队列加了监控。连续3次重试失败就告警人工介入处理。这样既不阻塞主流程也不会丢通知。java Scheduled(fixedDelay 5000) public void processRetryQueue() { ListNotifyRetryTask tasks retryQueue.pollBatch(50); for (NotifyRetryTask task : tasks) { try { notificationService.notify(task.getOrderId()); } catch (RpcException e) { task.incrementRetryCount(); if (task.getRetryCount() 3) { alertService.sendAlert(通知重试3次失败, orderId task.getOrderId()); } else { retryQueue.add(task); } } } }反思AI生成异常处理代码有个系统性问题——它只看到代码结构看不到业务语义。在AI眼里NotificationService是个可降级的服务通知失败了打个日志就够了。但在业务方眼里通知是支付流程的必要环节丢了就是事故。这种认知差距在代码review时很容易被忽略因为AI的改法在技术逻辑上是自洽的。你需要用业务视角去审视每一个catch块这个异常被吞了之后业务链路会不会断我现在有个习惯AI生成异常处理代码后逐个catch块问自己两个问题——这个异常被吞了上游知不知道业务链路断了有没有兜底机制两个答案都是有才放行。还有一点AI特别喜欢给catch加注释解释为什么不抛异常。这些注释看起来很专业实际上是在掩盖业务决策的缺失。注释写不影响主流程但你得自己判断——真的不影响吗AI替你做的这个决定你敢背锅吗