overleaf/overleaf · error · Errors.InvalidError

Cannot revert split test with ID '${name}' to previous versi

Error message

Cannot revert split test with ID '${name}' to previous version: split test must have at least 2 versions

What it means

Thrown by revertToPreviousVersion when the split test exists and is not archived but has only one version (versions.length <= 1). Reverting requires at least two versions so there is a prior version to fall back to. Raised as InvalidError (HTTP 400).

Source

Thrown at services/web/app/src/Features/SplitTests/SplitTestManager.mjs:362

  { name, versionNumber, comment },
  userId
) {
  const splitTest = await getSplitTest({ name })
  if (!splitTest) {
    throw new Errors.NotFoundError(
      `Cannot revert split test with ID '${name}' to previous version: not found`
    )
  }
  if (splitTest.archived) {
    throw new Errors.InvalidError(
      'Cannot revert an archived split test to previous version',
      {
        name,
      }
    )
  }
  if (splitTest.versions.length <= 1) {
    throw new Errors.InvalidError(
      `Cannot revert split test with ID '${name}' to previous version: split test must have at least 2 versions`
    )
  }
  const previousVersion = SplitTestUtils.getVersion(splitTest, versionNumber)
  if (!previousVersion) {
    throw new Errors.NotFoundError(
      `Cannot revert split test with ID '${name}' to version number ${versionNumber}: version not found`
    )
  }
  const lastVersion = SplitTestUtils.getCurrentVersion(splitTest)
  if (
    lastVersion.phase === RELEASE_PHASE &&
    previousVersion.phase !== RELEASE_PHASE
  ) {
    splitTest.forbidReleasePhase = true
  }
  const previousVersionCopy = previousVersion.toObject()
  previousVersionCopy.versionNumber = lastVersion.versionNumber + 1

View on GitHub (pinned to 28ad3b03b7)

Solutions

  1. Check `versions.length > 1` before calling revert; otherwise there is nothing to revert to.
  2. Manually edit/create a new version with the desired configuration instead of reverting.
  3. Restore version history if it was collapsed by a config sync.

Example fix

// before
await revertToPreviousVersion({ name: 'my-test', versionNumber: 1 })
// after
const test = await getSplitTest({ name: 'my-test' })
if (test.versions.length > 1) {
  await revertToPreviousVersion({ name: 'my-test', versionNumber: 1 })
}
Defensive patterns

Strategy: validation

Validate before calling

const test = await getSplitTest({ name })
if ((test?.versions?.length ?? 0) <= 1) {
  throw new Error(`split test '${name}' has no previous version to revert to`)
}

Type guard

function hasPreviousVersion(test) {
  return Array.isArray(test?.versions) && test.versions.length > 1
}

Try / catch

try {
  await revertToPreviousVersion({ name, versionNumber })
} catch (err) {
  if (err instanceof Errors.InvalidError && /at least 2 versions/.test(err.message)) {
    // create/edit a version manually instead
  } else throw err
}

Prevention

When it happens

Trigger: Calling revertToPreviousVersion on a freshly created test that has only its initial version; after a sync/merge rebuilt the test with a single version; passing versionNumber 1 (or the current version) on a single-version test.

Common situations: New tests where operators assume an implicit 'version 0' exists; tests recreated by _mergeAllSplitTestsInRawMode losing version history; scripts reverting without checking version count.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of overleaf/overleaf@28ad3b03b7 (2026-09-03). Data as JSON: /api/errors/0dba288738589f3e. Report an issue: GitHub.