{"record":{"id":"c56288ae99014a64","repo":"overleaf/overleaf","slug":"versionnotfounderror","errorCode":"VersionNotFoundError","errorMessage":"VersionNotFoundError","messagePattern":"VersionNotFoundError","errorType":"error_code","errorClass":"Chunk.VersionNotFoundError","httpStatus":404,"severity":"error","filePath":"services/history-v1/storage/lib/chunk_store/index.js","lineNumber":257,"sourceCode":"      preferNewer: opts.preferNewer,\n    }\n  )\n  const rawHistory = await historyStore.loadRaw(projectId, chunkRecord.id)\n  const history = History.fromRaw(rawHistory)\n  const startVersion = chunkRecord.endVersion - history.countChanges()\n\n  if (!opts.persistedOnly) {\n    // Try to extend the chunk with any non-persisted changes that\n    // follow the chunk's end version.\n    const nonPersistedChanges = await getChunkExtension(\n      projectId,\n      chunkRecord.endVersion\n    )\n    history.pushChanges(nonPersistedChanges)\n\n    // Check that the changes do actually contain the requested version\n    if (version > chunkRecord.endVersion + nonPersistedChanges.length) {\n      throw new Chunk.VersionNotFoundError(projectId, version)\n    }\n  }\n\n  await lazyLoadHistoryFiles(history, batchBlobStore)\n  return new Chunk(history, startVersion)\n}\n\n/**\n * Load the chunk that contains the version that was current at the given\n * timestamp, including blob metadata.\n *\n * @param {string} projectId\n * @param {Date} timestamp\n * @param {object} [opts]\n * @param {boolean} [opts.persistedOnly] - only include persisted changes\n */\nasync function loadAtTimestamp(projectId, timestamp, opts = {}) {\n  assert.projectId(projectId, 'bad projectId')","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/overleaf/overleaf/blob/28ad3b03b71cb4311decdcb55c36b33ec10d72db/services/history-v1/storage/lib/chunk_store/index.js#L239-L275","documentation":"loadAtVersion throws Chunk.VersionNotFoundError when the requested version exceeds the newest version reachable in the loaded chunk plus any non-persisted changes. The history loaded from storage does not extend far enough to contain the requested version.","triggerScenarios":"Calling loadAtVersion(projectId, version) (directly or via chunk/getChangesAtVersion) with a version greater than the latest chunk's endVersion plus the count of pending non-persisted changes, or a version beyond the end of project history.","commonSituations":"Client requesting a future/stale version number, version counters out of sync after a restore or clone, calling before pending changes were persisted, or off-by-one when computing versions.","solutions":["Clamp or validate the requested version against the latest endVersion (from getLatestChunkMetadata) before loading.","Flush/persist pending changes so non-persisted changes are included, then retry.","Use loadAtVersion with preferNewer or fall back to the latest available version."],"exampleFix":"// before\nconst chunk = await chunkStore.loadAtVersion(projectId, requestedVersion)\n// after\nconst latest = await chunkStore.getLatestChunkMetadata(projectId)\nif (requestedVersion > latest.endVersion) {\n  requestedVersion = latest.endVersion // or throw a client-visible 404\n}\nconst chunk = await chunkStore.loadAtVersion(projectId, requestedVersion)","handlingStrategy":"validation","validationCode":"const latest = await chunkStore.getLatestChunkMetadata(projectId)\nif (version < 0 || version > latest.endVersion) {\n  throw new Error(`version ${version} out of range (latest ${latest.endVersion})`)\n}","typeGuard":"function isVersionNotFound(err) {\n  return err instanceof Chunk.VersionNotFoundError\n}","tryCatchPattern":"try {\n  return await chunkStore.loadAtVersion(projectId, version)\n} catch (err) {\n  if (!(err instanceof Chunk.VersionNotFoundError)) throw err\n  return chunkStore.loadAtVersion(projectId, latestEndVersion) // fall back to latest\n}","preventionTips":["Clamp requested versions against getLatestChunkMetadata before loading.","Persist pending changes before serving historical reads that depend on them.","Keep client version counters in sync after restores, clones, or rollbacks."],"tags":["versioning","not-found","history-storage"],"backgroundTag":"version-not-found","analyzedSha":"28ad3b03b71cb4311decdcb55c36b33ec10d72db","analyzedAt":"2026-09-03T02:10:22.807Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T07:17:11.731Z"}