--- services/track-changes/app/js/DiffGenerator.js
+++ services/track-changes/app/js/DiffGenerator.js
@@ -63,6 +63,7 @@ module.exports = DiffGenerator = {
       if (p > max_p) {
         logger.warn({ max_p, p }, 'truncating position to content length')
         p = max_p
+        op.p = p // fix out of range offsets to avoid invalid history exports in ZipManager
       }

       const textToBeRemoved = content.slice(p, p + op.i.length)
@@ -74,6 +75,9 @@ module.exports = DiffGenerator = {

       return content.slice(0, p) + content.slice(p + op.i.length)
     } else if (op.d != null) {
+      if (op.p > content.length) {
+        op.p = content.length // fix out of range offsets to avoid invalid history exports in ZipManager
+      }
       return content.slice(0, op.p) + op.d + content.slice(op.p)
     } else {
       return content

--- services/web/modules/history-migration/app/src/HistoryUpgradeHelper.js
+++ services/web/modules/history-migration/app/src/HistoryUpgradeHelper.js
@@ -107,6 +107,15 @@ async function upgradeProject(project, options) {
   if (!upgradeFn) {
     return { error: 'unsupported history type' }
   }
+  if (options.forceClean) {
+    try {
+      const projectId = project._id
+      // delete any existing history stored in the mongo backend
+      await HistoryManager.promises.deleteProject(projectId, projectId)
+    } catch (err) {
+      // failed to delete existing history, but we can try to continue
+    }
+  }
   const result = await upgradeFn(project, options)
   result.historyType = historyType
   return result

--- services/web/scripts/history/migrate_history.js
+++ services/web/scripts/history/migrate_history.js
@@ -2,6 +2,25 @@
 process.env.MONGO_SOCKET_TIMEOUT =
   parseInt(process.env.MONGO_SOCKET_TIMEOUT, 10) || 3600000

+const fs = require('fs')
+
+if (fs.existsSync('/etc/container_environment.json')) {
+  try {
+    const envData = JSON.parse(
+      fs.readFileSync('/etc/container_environment.json', 'utf8')
+    )
+    for (const [key, value] of Object.entries(envData)) {
+      process.env[key] = value
+    }
+  } catch (err) {
+    console.error(
+      'cannot read /etc/container_environment.json, the script needs to be run as root',
+      err
+    )
+    process.exit(1)
+  }
+}
+
 const VERSION = '0.9.0-cli'
 const {
   countProjects,
@@ -11,7 +30,6 @@ const {
 } = require('../../modules/history-migration/app/src/HistoryUpgradeHelper')
 const { waitForDb } = require('../../app/src/infrastructure/mongodb')
 const minimist = require('minimist')
-const fs = require('fs')
 const util = require('util')
 const pLimit = require('p-limit')
 const logger = require('@overleaf/logger')
@@ -34,6 +52,7 @@ const argv = minimist(process.argv.slice(2), {
     'use-query-hint',
     'retry-failed',
     'archive-on-failure',
+    'force-clean',
   ],
   string: ['output', 'user-id'],
   alias: {
@@ -168,6 +187,7 @@ async function migrateProjects(projectsToMigrate) {
     convertLargeDocsToFile: argv['convert-large-docs-to-file'],
     userId: argv['user-id'],
     reason: VERSION,
+    forceClean: argv['force-clean'],
   }
   async function _migrateProject(project) {
     if (INTERRUPT) {
