{"record":{"id":"d4f1e1ce061e7511","repo":"apache/druid","slug":"failed-to-insert-upgrade-segments-in-db-s","errorCode":null,"errorMessage":"Failed to insert upgrade segments in DB: %s","messagePattern":"Failed to insert upgrade segments in DB: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"server/src/main/java/org/apache/druid/metadata/IndexerSQLMetadataStorageCoordinator.java","lineNumber":2228,"sourceCode":"        DataSegment segment = entry.getKey();\n        ReplaceTaskLock lock = entry.getValue();\n        batch.add()\n             .bind(\"task_id\", lock.getSupervisorTaskId())\n             .bind(\"segment_id\", segment.getId().toString())\n             .bind(\"lock_version\", lock.getVersion());\n      }\n      final int[] affectedAppendRows = batch.execute();\n\n      final List<DataSegment> failedInserts = new ArrayList<>();\n      for (int i = 0; i < partition.size(); ++i) {\n        if (affectedAppendRows[i] != 1) {\n          failedInserts.add(partition.get(i).getKey());\n        } else {\n          inserted++;\n        }\n      }\n      if (!failedInserts.isEmpty()) {\n        throw new ISE(\n            \"Failed to insert upgrade segments in DB: %s\",\n            SegmentUtils.commaSeparatedIdentifiers(failedInserts)\n        );\n      }\n    }\n    return inserted;\n  }\n\n  private List<DataSegmentPlus> retrieveSegmentsById(\n      String dataSource,\n      SegmentMetadataReadTransaction transaction,\n      Set<String> segmentIds\n  )\n  {\n    if (segmentIds.isEmpty()) {\n      return Collections.emptyList();\n    }\n","sourceCodeStart":2210,"sourceCodeEnd":2246,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/metadata/IndexerSQLMetadataStorageCoordinator.java#L2210-L2246","documentation":"During segment upgrade/insertion, IndexerSQLMetadataStorageCoordinator batch-inserts upgraded segment rows into the segments table. After the batch it checks for failed inserts and throws IllegalStateException listing the segment identifiers that could not be written. This almost always means one or more segments already exist in the database with conflicting content.","triggerScenarios":"Running metadata-store upgrade/repair tooling (e.g. kill/restore or segment schema upgrade flows) where some upgraded segments already have rows in druid_segments, causing INSERT failures collected in failedInserts.","commonSituations":"Re-running an upgrade job after a partial previous run; duplicate segment identifiers produced by re-ingestion; database unique-key violations on segment id due to conflicting payloads.","solutions":["Identify the failing segments from the comma-separated list in the message and check for existing rows in druid_segments with those IDs.","Delete or reconcile the stale/conflicting segment rows before retrying the upgrade.","Make the upgrade idempotent: skip segments whose existing row is already correct instead of re-inserting.","Check for overlapping ingestion tasks that may have created duplicate segment identifiers."],"exampleFix":"// before\ncoordinator.insertSegments(upgradedSegments); // throws listing failures\n// after\nList<DataSegment> toInsert = upgradedSegments.stream()\n    .filter(s -> !segmentsTableContains(s.getId()))\n    .collect(Collectors.toList());\ncoordinator.insertSegments(toInsert);","handlingStrategy":"try-catch","validationCode":"List<String> existing = getExistingSegmentIds(candidateSegments);\nList<DataSegment> insertable = candidateSegments.stream()\n    .filter(s -> !existing.contains(s.getId().toString()))\n    .collect(Collectors.toList());","typeGuard":null,"tryCatchPattern":"try {\n  coordinator.insertSegments(upgradedSegments);\n} catch (IllegalStateException e) {\n  log.error(e, \"Segment upgrade inserts failed\");\n  // parse failed identifiers from message, reconcile DB rows, retry\n}","preventionTips":["Make segment upgrade jobs idempotent (check-before-insert)","Avoid re-running upgrades concurrently","Monitor for duplicate segment identifiers from ingestion","Back up the segments table before bulk metadata operations"],"tags":["metadata","database","segments","duplicate-key"],"backgroundTag":"database-write-failed","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}