overleaf/overleaf · error · Chunk.VersionNotFoundError

VersionNotFoundError

VersionNotFoundError

Error message

VersionNotFoundError

What it means

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.

Source

Thrown at services/history-v1/storage/lib/chunk_store/index.js:257

      preferNewer: opts.preferNewer,
    }
  )
  const rawHistory = await historyStore.loadRaw(projectId, chunkRecord.id)
  const history = History.fromRaw(rawHistory)
  const startVersion = chunkRecord.endVersion - history.countChanges()

  if (!opts.persistedOnly) {
    // Try to extend the chunk with any non-persisted changes that
    // follow the chunk's end version.
    const nonPersistedChanges = await getChunkExtension(
      projectId,
      chunkRecord.endVersion
    )
    history.pushChanges(nonPersistedChanges)

    // Check that the changes do actually contain the requested version
    if (version > chunkRecord.endVersion + nonPersistedChanges.length) {
      throw new Chunk.VersionNotFoundError(projectId, version)
    }
  }

  await lazyLoadHistoryFiles(history, batchBlobStore)
  return new Chunk(history, startVersion)
}

/**
 * Load the chunk that contains the version that was current at the given
 * timestamp, including blob metadata.
 *
 * @param {string} projectId
 * @param {Date} timestamp
 * @param {object} [opts]
 * @param {boolean} [opts.persistedOnly] - only include persisted changes
 */
async function loadAtTimestamp(projectId, timestamp, opts = {}) {
  assert.projectId(projectId, 'bad projectId')

View on GitHub (pinned to 28ad3b03b7)

Solutions

  1. Clamp or validate the requested version against the latest endVersion (from getLatestChunkMetadata) before loading.
  2. Flush/persist pending changes so non-persisted changes are included, then retry.
  3. Use loadAtVersion with preferNewer or fall back to the latest available version.

Example fix

// before
const chunk = await chunkStore.loadAtVersion(projectId, requestedVersion)
// after
const latest = await chunkStore.getLatestChunkMetadata(projectId)
if (requestedVersion > latest.endVersion) {
  requestedVersion = latest.endVersion // or throw a client-visible 404
}
const chunk = await chunkStore.loadAtVersion(projectId, requestedVersion)
Defensive patterns

Strategy: validation

Validate before calling

const latest = await chunkStore.getLatestChunkMetadata(projectId)
if (version < 0 || version > latest.endVersion) {
  throw new Error(`version ${version} out of range (latest ${latest.endVersion})`)
}

Type guard

function isVersionNotFound(err) {
  return err instanceof Chunk.VersionNotFoundError
}

Try / catch

try {
  return await chunkStore.loadAtVersion(projectId, version)
} catch (err) {
  if (!(err instanceof Chunk.VersionNotFoundError)) throw err
  return chunkStore.loadAtVersion(projectId, latestEndVersion) // fall back to latest
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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