# rpc 错误：code = FailedPrecondition desc = 资源版本不匹配：期望 42，实际 41

- **ID:** `go/grpc-failed-precondition`
- **领域:** go
- **类别:** data_error
- **验证级别:** ai_generated
- **修复率:** 80%

## 根因

服务器拒绝了操作，因为资源状态的前置条件未满足——通常是乐观并发控制，客户端携带的版本/etag 相对于服务器当前状态已过时。

## 版本兼容性

| 版本 | 状态 | 引入 | 弃用 |
|------|------|------|------|
| 1.x | active | — | — |

## 解决方案

1. **** (88% 成功率)
   ```
   Re-fetch the latest resource, apply the mutation to the fresh copy, and retry with the new version:

for i := 0; i < 5; i++ {
    cur, err := client.Get(ctx, &pb.GetReq{Id: id})
    if err != nil { return err }
    cur.Data = newData
    _, err = client.Update(ctx, &pb.UpdateReq{Id: id, Data: newData, Version: cur.Version})
    if status.Code(err) != codes.FailedPrecondition { return err }
}
   ```
2. **** (80% 成功率)
   ```
   Use an ETag/If-Match style conditional request and surface a conflict to the caller when it persists:

if status.Code(err) == codes.FailedPrecondition {
    return ErrConflict // let the caller resolve
}
   ```

## 无效尝试

- **** — The version is still stale; the server rejects every identical attempt with the same FailedPrecondition. (90% 失败率)
- **** — Removing the precondition bypasses concurrency control and risks last-writer-wins data loss. (70% 失败率)
