DynamoDB IdempotentParameterMismatchException
TL;DR — 你用一个在过去 10 分钟内已经用过的 ClientRequestToken 调用了 TransactWriteItems,但请求的其余部分变了。这个 token 承诺"这是_同一个_事务的重试"——因此 DynamoDB 会拒绝一个载荷不同的 token 复用。只为字节完全相同的重试复用 token;为每个新的逻辑事务铸造一个新 token(一个 UUID)。
含义
IdempotentParameterMismatchException: DynamoDB rejected the request because
you retried a request with a different payload but with an idempotent token
that was already used.ClientRequestToken 让 TransactWriteItems 具有幂等性:多次使用相同 token 的完全相同的调用具有单次调用的效果,这在超时掩盖了第一次尝试是否落地时保护你不会重复应用一个事务。一个 token 在首次使用它的请求完成后保持有效 10 分钟。如果一个请求在那个窗口内到达,带着相同的 token 但不同的参数,DynamoDB 既不能把它当作重试——也拒绝把它当作一个新事务。HTTP 400,原样不可重试。
为什么会发生
- 一个静态或硬编码的 token——每次事务都发送相同的 token 字符串,因此第二个(不同的)事务与第一个冲突。
- token 派生自过于粗粒度的东西——例如用户 ID 或表名,导致同一个用户的两个不同事务共享一个 token。
- 重试以不同方式重建了请求——一个项目内部的时间戳、TTL 值或生成的 ID 在第一次尝试和重试之间变了,因此"同一个"事务不再逐字节匹配。
- 两条代码路径共享一个 token 来源——用相同值播种的并行 worker。
如何修复
为每个逻辑事务生成一个唯一的 token——在组合事务的地方生成一个 UUID:
import {randomUUID} from 'node:crypto'; await client.send(new TransactWriteItemsCommand({ ClientRequestToken: token, // created ONCE per logical transaction TransactItems: [...] }));重试时把 token _随_请求一起保留——重试同一个已经构建好的请求对象,而不是一个重建的,这样载荷中就没有任何东西会漂移。(AWS SDK 为它们的自动重试正确地做到了这一点;bug 几乎总是一个重新组合请求的应用级重试。)
在组合之前固定易变的值——时间戳和生成的 ID 必须计算一次并在重试时复用,而不是重新求值。
不要在 10 分钟后复用一个 token 却期望幂等——过了窗口,请求会被当作全新的,并会被再次应用。
DynoTable 桌面应用让你检查一个事务确切触及了哪些项目,把"我的第一次尝试到底落地了吗?"从猜测变成一次查找。
相关错误
- TransactionCanceledException——事务运行了并被回滚。
- TransactionConflictException——一个并发事务触及了同一个项目。
- TransactWriteItems: too many items
- 代码示例:TransactWriteItems in Node.js——展示了 ClientRequestToken 的用法。
- 学习:DynamoDB transactions
References
- TransactWriteItems — Amazon DynamoDB API Reference (ClientRequestToken, IdempotentParameterMismatchException)
- Amazon DynamoDB Transactions: How it works — Developer Guide (idempotency)
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
最后核实于 2026-07-13,依据上方链接的 AWS 官方文档。