DuplicateItemException: 기본 키 중복

요약 — PartiQL INSERT는 엄격한 생성입니다. 같은 기본 키를 가진 항목이 이미 존재하면 DynamoDB는 이를 덮어쓰는 대신 DuplicateItemException을 던집니다. 기존 항목을 수정하려면 PartiQL UPDATE를 사용하고, PutItem의 "있으면 교체" 동작이 필요하다면 PutItem 자체를 사용하세요 — PartiQL INSERT는 의도적으로 결코 교체하지 않습니다.

무엇을 의미하는가

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

PartiQL 데이터 플레인(ExecuteStatement / ExecuteTransaction / BatchExecuteStatement)은 INSERT를 조건부 생성으로 매핑합니다 — 그 기본 키를 가진 항목이 없을 때만 성공합니다. 이는 기존 항목을 조용히 교체하는 네이티브 PutItem과 정반대의 기본 동작입니다. SQL에서 넘어와 INSERT가 중복 키에서 실패하기를 기대했다면 정확히 그 동작이고, upsert 동작을 기대했다면 이 오류가 뜻밖일 것입니다.

왜 발생하는가

  • 항목이 실제로 이미 존재함 — 재시도, 리플레이, 또는 두 작성자가 같은 키에 대해 INSERT를 경쟁적으로 보낸 경우.
  • 생성이 아니라 업데이트를 원했음PutItem 스타일 코드를 PartiQL로 옮기면서 INSERT가 교체한다고 가정한 경우.
  • 멱등하지 않은 재시도 루프 — 첫 시도는 성공했지만 응답이 유실되어(타임아웃) 재시도가 같은 키를 다시 삽입하는 경우.
  • 고유하지 않은 합성 키 — 조합한 파티션/정렬 키가 생각보다 자주 충돌하는 경우(예: 초 단위 정밀도의 타임스탬프).

어떻게 해결하는가

  1. 기존 항목을 업데이트하나요? UPDATE를 사용하세요:

    UPDATE "orders" SET status = 'shipped' WHERE pk = 'ORDER#123' AND sk = 'META'
  2. "있으면 교체"(PutItem 동작)를 원하나요? PutItem을 호출하세요 — PartiQL에는 upsert 구문이 없고, 네이티브 API의 기본 동작이 정확히 원하는 그 덮어쓰기입니다:

    await client.send(new PutItemCommand({TableName: 'orders', Item: item}));
  3. 생성이 멱등하다면 성공으로 처리하세요 — 첫 시도가 이미 기록한 항목에 대해 재시도가 DuplicateItemException을 만난다면, 이를 catch하고 무시하는 것이 흔히 올바른 처리입니다.

  4. 고유성에 의존한다면 INSERT를 유지하세요 — 이 예외가 생성 전용 가드이며, PutItem 조건의 attribute_not_exists()에 해당하는 PartiQL 버전입니다.

실제 데이터에 문을 실행해 보는 것이 INSERT/UPDATE 구분을 체득하는 가장 빠른 방법입니다 — DynoTable의 PartiQL 편집기는 인라인 진단과 빠른 수정과 함께 라이브 테이블에 문을 실행하며, DynamoDB Expression BuilderPutItem 동작이 필요할 때 그에 해당하는 네이티브 API 요청을 생성해 줍니다.

재현하기

이미 존재하는 기본 키에 대한 PartiQL INSERT:

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'}`
  })
);

실제 출력:

DuplicateItem: Duplicate primary key exists in table
HTTP 400

로컬에서 테스트한다면 알아 둘 만한 점이 있습니다. DynamoDB Local은 이를 위와 같은 짧은 메시지의 DuplicateItem으로 드러내는 반면, 서비스 API 참조 문서는 더 긴 문장과 함께 DuplicateItemException으로 문서화합니다. 정확한 이름이나 문구가 아니라 HTTP 400과 작업 종류로 매칭하세요. 그러지 않으면 핸들러가 Local과 실제 테이블에서 다르게 동작합니다.

관련 오류

참고 자료

위에 링크된 공식 AWS 문서를 기준으로 2026-07-13에 마지막으로 검증했습니다.

2026-07-26에 DynamoDB Local 2.x와 AWS SDK for JavaScript v3.1095.0으로 재현했습니다 — 위 출력은 그대로 옮긴 것입니다.

Console 없이 DynamoDB 작업하기

DynamoDB로는 실행할 수 없는 진짜 SQL(JOINs, GROUP BY, 집계)을 실행하는 빠른 DynamoDB 데스크톱 클라이언트. 시각적 편집과 여러분 자신의 Bedrock 키로 동작하는 AI 에이전트를 제공합니다.

30일 무료 체험, 신용카드 불필요 — 이후 기간 제한 없는 무료 요금제.