overleaf/overleaf · error · OError

Project blocked from loading docs

Error message

Project blocked from loading docs

What it means

putDocInMemory throws this OError when the project is currently blocked from loading docs (Redis key indicating the project was blocked, e.g. after too many concurrent load attempts or a project-level lock). Docs are refused to avoid adding docIds to a blocked project's docsInProject set while it is being unloaded or quarantined.

Source

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

    logger.debug(
      { projectId, docId, version, docHash, pathname, projectHistoryId },
      'putting doc in redis'
    )
    ranges = RedisManager._serializeRanges(ranges)

    // update docsInProject set before writing doc contents
    const projectBlockMulti = rclient.multi()
    projectBlockMulti.exists(keys.projectBlock({ project_id: projectId }))
    projectBlockMulti.sadd(keys.docsInProject({ project_id: projectId }), docId)
    const reply = await projectBlockMulti.exec()
    const projectBlocked = reply[0] === 1
    if (projectBlocked) {
      // We don't clean up the spurious docId added in the docsInProject
      // set. There is a risk that the docId was successfully added by a
      // concurrent process.  This set is used when unloading projects. An
      // extra docId will not prevent the project from being uploaded, but
      // a missing docId means that the doc might stay in Redis forever.
      throw new OError('Project blocked from loading docs', { projectId })
    }

    await RedisManager.setHistoryRangesSupportFlag(docId, historyRangesSupport)

    if (!pathname) {
      metrics.inc('pathname', 1, {
        path: 'RedisManager.setDoc',
        status: pathname === '' ? 'zero-length' : 'undefined',
      })
    }

    // Make sure that this MULTI operation only operates on doc
    // specific keys, i.e. keys that have the doc id in curly braces.
    // The curly braces identify a hash key for Redis and ensures that
    // the MULTI's operations are all done on the same node in a
    // cluster environment.
    const multi = rclient.multi()
    multi.mset({

View on GitHub (pinned to 28ad3b03b7)

Solutions

  1. Wait for the block TTL to expire and retry loading the project
  2. Clear the project block key in Redis if it is stale (rclient DEL the block key) after verifying the project is healthy
  3. Investigate why the project got blocked (too many docs / memory pressure) and reduce doc count or size
  4. Check for retry storms from web hammering loadDoc and add backoff

Example fix

try {
  await documentUpdaterHandler.promises.flushProjectToMongo(projectId)
} catch (err) {
  if (err.message === 'Project blocked from loading docs') {
    await timer(30_000) // let the block expire
    return retry()
  }
  throw err
}
Defensive patterns

Strategy: retry

Try / catch

try {
  await putDocInMemory(...)
} catch (err) {
  if (err.message === 'Project blocked from loading docs') return retryAfterBlockExpiry(projectId)
  throw err
}

Prevention

When it happens

Trigger: Calling putDocInMemory while the project block flag exists in Redis (projectBlocked truthy), typically set when the project exceeds concurrency/size limits or during controlled unloading.

Common situations: Projects with very large numbers of docs hitting load limits; burst of concurrent loadDoc/flush requests after a project structure change; stale block flag left after a crash; misconfigured blocking thresholds.

Related errors


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