DynamoDB ConditionalCheckFailedException
TL;DR — Tu escritura llevaba un ConditionExpression que evaluó a false contra el item actual, así que DynamoDB rechazó la escritura y dejó el item intacto. Esto normalmente es lo esperado (concurrencia optimista, "crear si no existe") — captúralo y ramifica, no reintentes a ciegas.
Qué significa
A diferencia de una ValidationException, la petición estaba bien formada. DynamoDB evaluó tu condición y no se cumplió, así que el PutItem / UpdateItem / DeleteItem (o un item individual dentro de un TransactWriteItems) fue rechazado. Ningún dato cambió. Devuelve HTTP 400 y no es reintentable tal cual.
Por qué ocurre
- Guarda
attribute_not_exists(pk)en una creación — el item ya existe (un insert duplicado). - Guarda
attribute_exists(pk)en una actualización/eliminación — el item ya no está. - Concurrencia optimista — una comprobación
version = :expected(oupdatedAt) donde otro escritor llegó primero. - Guardas de regla de negocio —
balance >= :amount,#status = :expectedque ya no coinciden con el item almacenado.
Cómo solucionarlo
- Trátalo como un resultado normal, no como un fallo. Captura la excepción y decide qué significa una condición fallida en tu flujo (el item ya existe → devuélvelo; versión obsoleta → vuelve a leer y reintenta con la nueva versión).
- Vuelve a leer el item actual. Establece
ReturnValuesOnConditionCheckFailure: 'ALL_OLD'para obtener el item que causó el fallo sin un segundo viaje de ida y vuelta — vuelve en la propia excepción (el campoItem), y no se consume capacidad de lectura. - Vuelve a leer + recalcula para la concurrencia, y luego reintenta con la versión fresca — no reenvíes simplemente el mismo valor esperado.
Ese bucle de releer y comparar es exactamente lo que hace el área de preparación de DynoTable con las ediciones manuales — prepara tus escrituras y, ante un conflicto de bloqueo optimista, te muestra el Item actual junto a tu cambio para que lo resuelvas antes de que se envíe nada.
Ejemplo
import {DynamoDBClient} from '@aws-sdk/client-dynamodb';
import {DynamoDBDocumentClient, PutCommand} from '@aws-sdk/lib-dynamodb';
import {ConditionalCheckFailedException} from '@aws-sdk/client-dynamodb';
const doc = DynamoDBDocumentClient.from(new DynamoDBClient({}));
try {
await doc.send(
new PutCommand({
TableName: 'Users',
Item: {pk: 'USER#1', email: 'a@b.com'},
ConditionExpression: 'attribute_not_exists(pk)' // create-only
})
);
} catch (err) {
if (err instanceof ConditionalCheckFailedException) {
// Expected: the user already exists. Handle gracefully.
return {alreadyExists: true};
}
throw err;
}FAQ
¿Qué causa una ConditionalCheckFailedException en DynamoDB? Una escritura (PutItem, UpdateItem, DeleteItem o un item de TransactWrite) llevaba un ConditionExpression que evaluó a false contra el item actual — por ejemplo attribute_not_exists(pk) sobre una clave que ya existe, o una comprobación de versión que ya no coincide. DynamoDB rechaza la escritura y deja el item sin cambios.
¿Cómo evito que una ConditionalCheckFailedException tumbe mi aplicación? Captura la excepción y trátala como un resultado esperado, no como un fallo. Una condición fallida normalmente significa "alguien llegó primero" (concurrencia optimista) o "el item ya existe" — ramifica sobre ella en lugar de reintentar a ciegas.
Reproducirlo
Un PutItem protegido por attribute_not_exists contra una clave que sí existe:
await client.send(
new PutItemCommand({
TableName: 'orders',
Item: {pk: {S: 'ORDER#1'}, sk: {S: 'META'}},
ConditionExpression: 'attribute_not_exists(pk)'
})
);Salida real:
ConditionalCheckFailedException: The conditional request failed
HTTP 400El mensaje es deliberadamente poco informativo — nunca dice qué parte de la condición falló, ni qué contenía realmente el item. Pasa ReturnValuesOnConditionCheckFailure: "ALL_OLD" y el item actual vuelve en error.Item, lo que convierte esto de una conjetura en un diff.
Errores relacionados
- TransactionCanceledException — una condición fallida dentro de una transacción.
- ValidationException (visión general)
- Ejemplo de código: Escritura condicional en Node.js · en Python (boto3) — patrones de ConditionExpression ejecutables.
- Aprende: Expresiones de condición · Contadores atómicos
Referencias
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
- PutItem — Amazon DynamoDB API Reference
- DynamoDB condition expression examples — Amazon DynamoDB Developer Guide
Verificado por última vez el 2026-07-13 contra la documentación oficial de AWS enlazada arriba.
Reproducido el 2026-07-26 contra DynamoDB Local 2.x con AWS SDK for JavaScript v3.1095.0 — la salida de arriba es literal.