diff --git a/castor/db/oracleCommon.schema.sql b/castor/db/oracleCommon.schema.sql
index 9d73e9ad2bd799037601d234fad18ab972b5f147..b6e953ccef6c39278a634cc5585b24bd7a5147e6 100644
--- a/castor/db/oracleCommon.schema.sql
+++ b/castor/db/oracleCommon.schema.sql
@@ -417,7 +417,8 @@ CREATE GLOBAL TEMPORARY TABLE FilesToRecallHelper
  ON COMMIT DELETE ROWS;
 
 CREATE GLOBAL TEMPORARY TABLE FilesToMigrateHelper
- (fileId NUMBER, nsHost VARCHAR2(100), lastKnownFileName VARCHAR2(2048), filePath VARCHAR2(2048),
+ (fileId NUMBER CONSTRAINT UN_FilesToMigrateHelper_fileId UNIQUE,
+  nsHost VARCHAR2(100), lastKnownFileName VARCHAR2(2048), filePath VARCHAR2(2048),
   fileTransactionId NUMBER, fileSize NUMBER, fSeq INTEGER)
  ON COMMIT DELETE ROWS;
 
diff --git a/castor/db/oracleTapeGateway.sql b/castor/db/oracleTapeGateway.sql
index 90e759e93e33c0d3c4383d0aaa3497978affa4d1..abebd5c6350cf3ebbbee70b9b65253167d7da6a7 100644
--- a/castor/db/oracleTapeGateway.sql
+++ b/castor/db/oracleTapeGateway.sql
@@ -1007,6 +1007,8 @@ CREATE OR REPLACE PROCEDURE tg_getBulkFilesToMigrate(inLogContext IN VARCHAR2,
   varVid VARCHAR2(10);
   varNewFseq INTEGER;
   varFileTrId NUMBER;
+  CONSTRAINT_VIOLATED EXCEPTION;
+  PRAGMA EXCEPTION_INIT(CONSTRAINT_VIOLATED, -00001);
 BEGIN
   BEGIN
     -- Get id, VID and last valid fseq for this migration mount, lock
@@ -1047,12 +1049,18 @@ BEGIN
                                           AND copyNb != MigrationJob.destCopyNb))
        FOR UPDATE OF MigrationJob.id SKIP LOCKED)
   LOOP
+    BEGIN
+      -- Try to take this candidate on this mount
+      INSERT INTO FilesToMigrateHelper (fileId, nsHost, lastKnownFileName, filePath, fileTransactionId, fileSize, fseq)
+        VALUES (Cand.fileId, Cand.nsHost, Cand.lastKnownFileName, Cand.filePath, ids_seq.NEXTVAL, Cand.fileSize, varNewFseq)
+        RETURNING fileTransactionId INTO varFileTrId;
+    EXCEPTION WHEN CONSTRAINT_VIOLATED THEN
+      -- If we fail here, it means that another copy of this file was already selected for this mount.
+      -- Not a big deal, we skip this candidate and keep going.
+      CONTINUE;
+    END;
     varCount := varCount + 1;
     varTotalSize := varTotalSize + Cand.fileSize;
-    INSERT INTO FilesToMigrateHelper (fileId, nsHost, lastKnownFileName, filePath, fileTransactionId, fileSize, fseq)
-      VALUES (Cand.fileId, Cand.nsHost, Cand.lastKnownFileName, Cand.filePath, ids_seq.NEXTVAL, Cand.fileSize, varNewFseq)
-      RETURNING fileTransactionId INTO varFileTrId;
-    -- Take this candidate on this mount
     UPDATE MigrationJob
        SET status = tconst.MIGRATIONJOB_SELECTED,
            vid = varVid,