PutItem de DynamoDB en Node.js (SDK de AWS v3)
PutItem escribe un Item entero y reemplaza cualquier Item existente con la misma clave principal (las acciones basadas en Item cubren en qué se diferencia de UpdateItem). El cliente v3 envía DynamoDB JSON directamente, así que Item contiene valores { S: … } / { N: … } en lugar de JavaScript plano.
Código
import {DynamoDBClient, PutItemCommand} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
const command = new PutItemCommand({
TableName: 'Music',
Item: {
Artist: {S: 'Arturo Sandoval'},
SongTitle: {S: 'Cubano Chant'},
AlbumTitle: {S: 'Danzon'},
Year: {N: '1994'},
Awards: {N: '0'}
},
ConditionExpression: 'attribute_not_exists(#cond0) AND attribute_not_exists(#cond1)',
ExpressionAttributeNames: {
'#cond0': 'Artist',
'#cond1': 'SongTitle'
}
});
try {
await client.send(command);
console.log('Song written');
} catch (err) {
if (err.name === 'ConditionalCheckFailedException') {
console.log('A song with that key already exists — not overwritten');
} else {
throw err;
}
}Explicación
err.name es la comprobación correcta, y no es lo único que trae el error. Capturar la condición fallida de arriba e imprimir el objeto dio:
err.name ConditionalCheckFailedException
err instanceof Error true
err.message The conditional request failed
err.$metadata.httpStatusCode 400Cada error de v3 lleva $metadata con el código de estado, el id de la petición y el número de intento, que es lo que quieres en una línea de log. err.name es estable entre los paquetes modulares; instanceof ConditionalCheckFailedException también funciona, pero arrastra la clase como import de valor, así que los bundlers la conservan.
El error puede entregarte el Item que bloqueó la escritura. Añade ReturnValuesOnConditionCheckFailure: 'ALL_OLD' al comando y err.Item llega relleno: cinco atributos en la ejecución de arriba, con Year como {"N":"1994"}. La mayoría de los manejadores de solo creación hacen un GetItem tras el fallo para averiguar qué había ya. Ese viaje de ida y vuelta es evitable. (ReturnValues: 'ALL_OLD' es el primo del camino de éxito; ReturnValues cubre el resto.)
marshall() rechaza más entradas de las que esperas. Cambiar el Item tipado de esta página por DynamoDBDocumentClient y objetos planos es el siguiente paso habitual, y @aws-sdk/util-dynamodb es estricto por defecto. Tres excepciones reales, literales:
{Genre: undefined} Pass options.removeUndefinedValues=true to remove undefined values from map/array/set.
{tags: new Set()} Pass a non-empty set, or options.convertEmptyValues=true.
{n: 9007199254740993} Number 9007199254740992 is greater than Number.MAX_SAFE_INTEGER. Use NumberValue from @aws-sdk/lib-dynamodb.La primera es la que llega a producción: un campo opcional que es undefined en vez de estar ausente lanza en tiempo de marshalling, y removeUndefinedValues: true en DynamoDBDocumentClient.from(client, {marshallOptions}) es el arreglo estándar.
Lee otra vez la tercera línea. El literal era 9007199254740993; el mensaje cita 9007199254740992. JavaScript ya había redondeado el valor antes de que el SDK lo viera siquiera, así que el SDK informa de lo que recibió. Esta es toda la razón por la que DynamoDB transporta N como cadena: soporta 38 dígitos de precisión, y un number de JS soporta de 15 a 17. Todo lo que sea realmente un identificador va en S, y todo lo que sea realmente un decimal va en NumberValue o en una cadena que formatees tú.
ConditionExpression cuesta capacidad de escritura incluso cuando dice que no. AWS: "if the expression evaluates to false, DynamoDB still consumes write capacity units from the table" (consultado el 2026-07-28). Un bucle cerrado de reintento de solo creación se factura por intento. Como calibración, un put con éxito de un Item de ~15 KB informó de "CapacityUnits": 15; las escrituras redondean al alza por cada 1 KB, en vez de los 4 KB que usan las lecturas.
Los alias son estructurales. #cond0/#cond1 resuelven a Artist/SongTitle a través de ExpressionAttributeNames. Los nombres en línea funcionan hasta que uno choca con una palabra reservada, y entonces la expresión falla por un atributo que ni tocaste.
Hazlo visualmente
Las reglas de marshalling de arriba son más fáciles de comprobar viendo ambas formas una al lado de la otra. El conversor de DynamoDB JSON gratuito convierte JSON plano a la forma tipada { S: … } y viceversa, para que confirmes qué habría producido marshall() antes de enviarlo.
Para escribir y editar Items contra tus propias tablas — un formulario por atributo, selectores de tipo, copiar el resultado de vuelta como código del SDK v3 —, descarga DynoTable.
Guías relacionadas
- Expresiones de condición de DynamoDB —
attribute_not_exists, bloqueo optimista y más. - Tipos de datos de DynamoDB — cómo se escribe cada tipo de atributo.
- DynamoDB ConditionalCheckFailedException — qué lanza la condición de solo creación cuando el Item ya existe.
- DynamoDB ValidationException — el cajón de sastre para un Item o una expresión mal formados.
Referencias
- PutItem — Amazon DynamoDB API Reference
- PutItemCommand — AWS SDK for JavaScript v3 Reference
- Capacity unit consumption — Amazon DynamoDB Developer Guide
- Condition expressions — Amazon DynamoDB Developer Guide
- Working with items and attributes — Amazon DynamoDB Developer Guide
Reproducido el 2026-07-28 en Node v24.18.0 con @aws-sdk/client-dynamodb 3.1095.0 y @aws-sdk/util-dynamodb 3.996.7, contra DynamoDB Local (amazon/dynamodb-local) en el puerto 9000. Las cadenas de error, la forma del objeto y la lectura de capacidad son salida capturada, copiada literalmente.