DuplicateItemException: chiave primaria duplicata
In breve — Un INSERT PartiQL è una creazione rigorosa: se un Item con la stessa chiave primaria esiste già, DynamoDB lancia DuplicateItemException invece di sovrascriverlo. Per modificare l'Item esistente usa UPDATE PartiQL; per ottenere la semantica replace-if-exists di PutItem, usa PutItem stesso — l'INSERT PartiQL deliberatamente non sostituisce mai.
Cosa 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.Il data-plane PartiQL (ExecuteStatement / ExecuteTransaction / BatchExecuteStatement) mappa INSERT a una creazione condizionale — riesce solo quando nessun Item con quella chiave primaria esiste. È il default opposto rispetto al PutItem nativo, che sostituisce silenziosamente un Item esistente. Se vieni da SQL aspettandoti che INSERT fallisca su una chiave duplicata, è esattamente questo comportamento; se ti aspettavi una semantica di upsert, questo errore è la sorpresa.
Perché succede
- L'Item esiste genuinamente già — un retry, un replay, o due writer in race sulla stessa chiave che emettono entrambi
INSERT. - Volevi un aggiornamento, non una creazione — porting di codice in stile
PutItema PartiQL presumendo cheINSERTsostituisca. - Un loop di retry non idempotente — il primo tentativo è riuscito ma la risposta è andata persa (timeout), e il retry reinserisce la stessa chiave.
- Una chiave sintetica non unica — la partition/sort key che componi collide più spesso di quanto pensi (es. un timestamp con precisione al secondo).
Come risolverlo
Stai aggiornando un Item esistente? Usa
UPDATE:UPDATE "orders" SET status = 'shipped' WHERE pk = 'ORDER#123' AND sk = 'META'Vuoi replace-if-exists (semantica PutItem)? Chiama
PutItem— PartiQL non ha uno statement di upsert, e il default dell'API nativa è esattamente la sovrascrittura che cerchi:await client.send(new PutItemCommand({TableName: 'orders', Item: item}));Trattalo come un successo quando la creazione è idempotente — se un retry incontra
DuplicateItemExceptionper un Item che il tuo primo tentativo ha già scritto, intercettarlo e ignorarlo è spesso la gestione corretta.Mantieni
INSERTquando fai affidamento sull'unicità — l'eccezione è il tuo guard create-only, l'equivalente PartiQL diattribute_not_exists()su una condizionePutItem.
Provare gli statement contro dati reali è il modo più rapido per interiorizzare la divisione INSERT/UPDATE — l'editor PartiQL di DynoTable esegue gli statement sulle tue tabelle live con diagnostica inline e quick-fix, e il DynamoDB Expression Builder emette le richieste equivalenti dell'API nativa quando ti serve invece la semantica di PutItem.
Riproducilo
Un INSERT PartiQL per una chiave primaria che esiste già:
await client.send(
new PutItemCommand({
TableName: 'orders',
Item: {pk: {S: 'ORDER#1'}, sk: {S: 'META'}}
})
);
await client.send(
new ExecuteStatementCommand({
Statement: `INSERT INTO "orders" VALUE {'pk':'ORDER#1','sk':'META'}`
})
);Output reale:
DuplicateItem: Duplicate primary key exists in table
HTTP 400Vale la pena saperlo se testi in locale: DynamoDB Local espone questo errore come DuplicateItem con il messaggio breve qui sopra, mentre il riferimento dell'API del servizio lo documenta come DuplicateItemException con una frase più lunga. Fai il match sull'HTTP 400 più l'operazione, non sul nome o sulla formulazione esatti, altrimenti il tuo handler si comporterà diversamente contro Local rispetto alla tabella reale.
Errori correlati
- ConditionalCheckFailedException — il gemello dell'API nativa: guard
attribute_not_exists()che fallisce suPutItem. - ValidationException: Unexpected from source — l'altro rifiuto PartiQL comune.
- Impara: PartiQL examples · PartiQL vs SQL
Riferimenti
- ExecuteStatement — Amazon DynamoDB API Reference (DuplicateItemException)
- PartiQL insert statements for DynamoDB — Developer Guide
- PartiQL update statements for DynamoDB — Developer Guide
Ultima verifica 2026-07-13 rispetto alla documentazione ufficiale AWS collegata sopra.
Riprodotto il 2026-07-26 su DynamoDB Local 2.x con AWS SDK for JavaScript v3.1095.0 — l'output qui sopra è riportato alla lettera.