PutItem do DynamoDB em Node.js (AWS SDK v3)

O PutItem escreve um item inteiro e substitui qualquer item existente com a mesma chave primária (ações baseadas em item cobre como isso difere do UpdateItem). O cliente v3 envia DynamoDB JSON diretamente, então Item contém valores { S: … } / { N: … } em vez de JavaScript puro.

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;
  }
}

Explicação

err.name é a verificação certa, e não é a única coisa no erro. Capturar a condição que falhou acima e imprimir o objeto deu:

err.name                     ConditionalCheckFailedException
err instanceof Error         true
err.message                  The conditional request failed
err.$metadata.httpStatusCode 400

Todo erro v3 carrega $metadata com o código de status, o id da requisição e a contagem de tentativas, que é o que você quer em uma linha de log. err.name é estável entre os pacotes modulares; instanceof ConditionalCheckFailedException também funciona, mas puxa a classe como import de valor, então os bundlers a mantêm.

O erro pode te entregar o item que bloqueou a escrita. Adicione ReturnValuesOnConditionCheckFailure: 'ALL_OLD' ao comando e err.Item chega preenchido: cinco atributos na execução acima, com Year como {"N":"1994"}. A maioria dos handlers de criação-apenas faz um GetItem depois da falha para descobrir o que já estava lá. Esse ida-e-volta é evitável. (ReturnValues: 'ALL_OLD' é o primo do caminho de sucesso; ReturnValues cobre o resto.)

O marshall() recusa mais entradas do que você espera. Trocar o Item tipado desta página por DynamoDBDocumentClient e objetos simples é o próximo passo habitual, e o @aws-sdk/util-dynamodb é estrito por padrão. Três erros reais, literais:

{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.

O primeiro é o que chega em produção: um campo opcional que é undefined em vez de ausente lança erro no momento do marshal, e removeUndefinedValues: true em DynamoDBDocumentClient.from(client, {marshallOptions}) é a correção padrão.

Leia a terceira linha de novo. O literal era 9007199254740993; a mensagem cita 9007199254740992. O JavaScript já tinha arredondado o valor antes de o SDK sequer vê-lo, então o SDK está reportando o que recebeu. Essa é toda a razão pela qual o DynamoDB transporta N como string: ele guarda 38 dígitos de precisão, e um number do JS guarda de 15 a 17. Qualquer coisa que é de fato um identificador pertence a S, e qualquer coisa que é de fato um decimal pertence a NumberValue ou a uma string que você mesmo formata.

ConditionExpression custa capacidade de escrita mesmo quando diz não. AWS: "if the expression evaluates to false, DynamoDB still consumes write capacity units from the table" (consultado em 2026-07-28). Um loop apertado de retry de criação-apenas é cobrado por tentativa. Para calibrar, um put bem-sucedido de um item de ~15 KB reportou "CapacityUnits": 15; escritas arredondam para cima a cada 1 KB em vez dos 4 KB que as leituras usam.

Os aliases são estruturais. #cond0/#cond1 resolvem para Artist/SongTitle através de ExpressionAttributeNames. Nomes inline funcionam até que um colida com uma palavra reservada, e aí a expressão falha em um atributo que você nem tocou.

Faça isso visualmente

As regras de marshalling acima são mais fáceis de conferir vendo as duas formas lado a lado. O conversor de DynamoDB JSON gratuito transforma JSON simples na forma tipada { S: … } e de volta, para que você possa confirmar o que o marshall() teria produzido antes de enviar.

Para escrever e editar itens nas suas próprias tabelas — um formulário por atributo, seletores de tipo, copiar o resultado de volta como código SDK v3 — baixe o DynoTable.

Guias relacionados

Referências

Reproduzido em 2026-07-28 no Node v24.18.0 com @aws-sdk/client-dynamodb 3.1095.0 e @aws-sdk/util-dynamodb 3.996.7, contra o DynamoDB Local (amazon/dynamodb-local) na porta 9000. As strings de erro, o formato do objeto e a leitura de capacidade são saída capturada, copiada literalmente.

Trabalhe com o DynamoDB sem o Console

Um cliente desktop rápido para DynamoDB que roda o SQL de verdade que o DynamoDB não consegue — JOINs, GROUP BY, agregações — com edição visual e um agente de IA com suas próprias chaves do Bedrock.

Teste grátis de 30 dias, sem cartão de crédito — depois o plano Grátis sem limite de tempo.