overleaf/overleaf · error

ranges are too large

Error message

ranges are too large

What it means

_serializeRanges JSON-stringifies the ranges object and throws a plain Error when the serialized form exceeds MAX_RANGES_SIZE. This prevents unboundedly large track-changes/comment range payloads from being stored in Redis and slowing down every subsequent doc load.

Source

Thrown at services/document-updater/app/js/RedisManager.js:616

      // Too late to lock the project
      await rclient.del(keys.projectBlock({ project_id: projectId }))
      return false
    }
    return true
  },

  async unblockProject(projectId) {
    const reply = await rclient.del(
      keys.projectBlock({ project_id: projectId })
    )
    const wasBlocked = reply === 1
    return wasBlocked
  },

  _serializeRanges(ranges) {
    let jsonRanges = JSON.stringify(ranges)
    if (jsonRanges && jsonRanges.length > MAX_RANGES_SIZE) {
      throw new Error('ranges are too large')
    }
    if (jsonRanges === '{}') {
      // Most doc will have empty ranges so don't fill redis with lots of '{}' keys
      jsonRanges = null
    }
    return jsonRanges
  },

  _deserializeRanges(ranges) {
    if (ranges == null || ranges === '') {
      return {}
    } else {
      return JSON.parse(ranges)
    }
  },

  _computeHash(docLines) {
    // use sha1 checksum of doclines to detect data corruption.

View on GitHub (pinned to 28ad3b03b7)

Solutions

  1. Accept/reject and delete old track-changes to shrink the ranges payload
  2. Resolve or remove stale comments in the document
  3. Raise MAX_RANGES_SIZE in RedisManager if legitimate workloads need more room
  4. Periodically compact/prune ranges via the track-changes service
  5. Archive very old documents and start fresh copies

Example fix

// before: letting ranges grow unbounded
await applyRangesUpdate(projectId, docId, incomingRanges)
// after: pre-trim ranges before pushing
function pruneRanges(ranges, maxSize = 1000) {
  const trimmed = {
    comments: (ranges.comments || []).slice(-maxSize),
    changes: (ranges.changes || []).slice(-maxSize),
  }
  if (JSON.stringify(trimmed).length > MAX_RANGES_SIZE) throw new Error('ranges too large after pruning')
  return trimmed
}
await applyRangesUpdate(projectId, docId, pruneRanges(ranges))
Defensive patterns

Strategy: validation

Validate before calling

const jsonRanges = JSON.stringify(ranges)
if (jsonRanges && jsonRanges.length > MAX_RANGES_SIZE) {
  throw new Error(`ranges payload too large: ${jsonRanges.length} > ${MAX_RANGES_SIZE}`)
}

Try / catch

try {
  const jsonRanges = RedisManager._serializeRanges(ranges)
  // proceed
} catch (err) {
  if (err.message === 'ranges are too large') {
    await pruneStaleRanges(projectId, docId) // accept/delete old track-changes, then retry
  } else {
    throw err
  }
}

Prevention

When it happens

Trigger: Calling updateDocument (which calls _serializeRanges) or _serializeRanges directly with a ranges object whose JSON representation is larger than MAX_RANGES_SIZE bytes.

Common situations: Very long-lived docs accumulating thousands of track-changes entries; comments never resolved/accepted over years of editing; an overly small MAX_RANGES_SIZE configured for a heavy-collaboration workflow.

Related errors


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