{"record":{"id":"0dba288738589f3e","repo":"overleaf/overleaf","slug":"cannot-revert-split-test-with-id-name-to-prev-0dba28","errorCode":null,"errorMessage":"Cannot revert split test with ID '${name}' to previous version: split test must have at least 2 versions","messagePattern":"Cannot revert split test with ID '(.+?)' to previous version: split test must have at least 2 versions","errorType":"validation","errorClass":"Errors.InvalidError","httpStatus":400,"severity":"error","filePath":"services/web/app/src/Features/SplitTests/SplitTestManager.mjs","lineNumber":362,"sourceCode":"  { name, versionNumber, comment },\n  userId\n) {\n  const splitTest = await getSplitTest({ name })\n  if (!splitTest) {\n    throw new Errors.NotFoundError(\n      `Cannot revert split test with ID '${name}' to previous version: not found`\n    )\n  }\n  if (splitTest.archived) {\n    throw new Errors.InvalidError(\n      'Cannot revert an archived split test to previous version',\n      {\n        name,\n      }\n    )\n  }\n  if (splitTest.versions.length <= 1) {\n    throw new Errors.InvalidError(\n      `Cannot revert split test with ID '${name}' to previous version: split test must have at least 2 versions`\n    )\n  }\n  const previousVersion = SplitTestUtils.getVersion(splitTest, versionNumber)\n  if (!previousVersion) {\n    throw new Errors.NotFoundError(\n      `Cannot revert split test with ID '${name}' to version number ${versionNumber}: version not found`\n    )\n  }\n  const lastVersion = SplitTestUtils.getCurrentVersion(splitTest)\n  if (\n    lastVersion.phase === RELEASE_PHASE &&\n    previousVersion.phase !== RELEASE_PHASE\n  ) {\n    splitTest.forbidReleasePhase = true\n  }\n  const previousVersionCopy = previousVersion.toObject()\n  previousVersionCopy.versionNumber = lastVersion.versionNumber + 1","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/overleaf/overleaf/blob/28ad3b03b71cb4311decdcb55c36b33ec10d72db/services/web/app/src/Features/SplitTests/SplitTestManager.mjs#L344-L380","documentation":"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).","triggerScenarios":"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.","commonSituations":"New tests where operators assume an implicit 'version 0' exists; tests recreated by _mergeAllSplitTestsInRawMode losing version history; scripts reverting without checking version count.","solutions":["Check `versions.length > 1` before calling revert; otherwise there is nothing to revert to.","Manually edit/create a new version with the desired configuration instead of reverting.","Restore version history if it was collapsed by a config sync."],"exampleFix":"// before\nawait revertToPreviousVersion({ name: 'my-test', versionNumber: 1 })\n// after\nconst test = await getSplitTest({ name: 'my-test' })\nif (test.versions.length > 1) {\n  await revertToPreviousVersion({ name: 'my-test', versionNumber: 1 })\n}","handlingStrategy":"validation","validationCode":"const test = await getSplitTest({ name })\nif ((test?.versions?.length ?? 0) <= 1) {\n  throw new Error(`split test '${name}' has no previous version to revert to`)\n}","typeGuard":"function hasPreviousVersion(test) {\n  return Array.isArray(test?.versions) && test.versions.length > 1\n}","tryCatchPattern":"try {\n  await revertToPreviousVersion({ name, versionNumber })\n} catch (err) {\n  if (err instanceof Errors.InvalidError && /at least 2 versions/.test(err.message)) {\n    // create/edit a version manually instead\n  } else throw err\n}","preventionTips":["Check version count before reverting","Remember newly created tests have only one version","Verify version history survived config syncs before rollback"],"tags":["split-test","invalid-state","versioning"],"backgroundTag":"invalid-state-transition","analyzedSha":"28ad3b03b71cb4311decdcb55c36b33ec10d72db","analyzedAt":"2026-09-03T02:10:22.807Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T07:17:11.731Z"}