DuplicateItemException: clave primaria duplicada

TL;DR — Un INSERT de PartiQL es una creación estricta: si ya existe un Item con la misma clave primaria, DynamoDB lanza DuplicateItemException en lugar de sobrescribirlo. Para modificar el Item existente usa UPDATE de PartiQL; para obtener la semántica de reemplazar-si-existe de PutItem, usa PutItem en sí — el INSERT de PartiQL deliberadamente nunca reemplaza.

Qué significa

DuplicateItemException: There was an attempt to insert an item with the
same primary key as an item that already exists in the DynamoDB table.

El plano de datos de PartiQL (ExecuteStatement / ExecuteTransaction / BatchExecuteStatement) mapea INSERT a una creación condicional — solo tiene éxito cuando no existe ningún Item con esa clave primaria. Ese es el valor por defecto opuesto al de PutItem nativo, que reemplaza en silencio un Item existente. Si vienes de SQL esperando que INSERT falle ante una clave duplicada, este es exactamente ese comportamiento; si esperabas semántica de upsert, este error es la sorpresa.

Por qué ocurre

  • El Item ya existe de verdad — un reintento, una repetición, o dos escritores compitiendo por la misma clave, ambos emitiendo INSERT.
  • Querías una actualización, no una creación — portar código de estilo PutItem a PartiQL y asumir que INSERT reemplaza.
  • Un bucle de reintento no idempotente — el primer intento tuvo éxito pero la respuesta se perdió (timeout), y el reintento vuelve a insertar la misma clave.
  • Una clave sintética que no es única — la clave de partición/ordenación que compones colisiona más a menudo de lo que crees (p. ej. una marca de tiempo con precisión de segundos).

Cómo solucionarlo

  1. ¿Actualizando un Item existente? Usa UPDATE:

    UPDATE "orders" SET status = 'shipped' WHERE pk = 'ORDER#123' AND sk = 'META'
  2. ¿Quieres reemplazar-si-existe (semántica de PutItem)? Llama a PutItem — PartiQL no tiene sentencia de upsert, y el valor por defecto de la API nativa es exactamente la sobrescritura que buscas:

    await client.send(new PutItemCommand({TableName: 'orders', Item: item}));
  3. Trátalo como éxito cuando la creación es idempotente — si un reintento choca con DuplicateItemException para un Item que tu primer intento ya escribió, capturarlo e ignorarlo suele ser la gestión correcta.

  4. Conserva INSERT cuando dependes de la unicidad — la excepción es tu guarda de solo-creación, el equivalente en PartiQL de attribute_not_exists() en una condición de PutItem.

Probar sentencias contra datos reales es la forma más rápida de interiorizar la división INSERT/UPDATE — la aplicación de escritorio DynoTable ejecuta PartiQL en un workbench SQL contra tus tablas en vivo, y el DynamoDB Expression Builder emite las solicitudes equivalentes de la API nativa cuando en su lugar necesitas semántica de PutItem.

Errores relacionados

Referencias

Verificado por última vez el 2026-07-13 contra la documentación oficial de AWS enlazada arriba.

Trabaja con DynamoDB sin la Consola

DynoTable es un cliente de escritorio rápido para DynamoDB: explora tablas, ejecuta consultas estilo SQL y edita Items localmente.