{"record":{"id":"fb5dff7e6d3b3a60","repo":"overleaf/overleaf","slug":"project-blocked-from-loading-docs","errorCode":null,"errorMessage":"Project blocked from loading docs","messagePattern":"Project blocked from loading docs","errorType":"exception","errorClass":"OError","httpStatus":null,"severity":"error","filePath":"services/document-updater/app/js/RedisManager.js","lineNumber":86,"sourceCode":"    logger.debug(\n      { projectId, docId, version, docHash, pathname, projectHistoryId },\n      'putting doc in redis'\n    )\n    ranges = RedisManager._serializeRanges(ranges)\n\n    // update docsInProject set before writing doc contents\n    const projectBlockMulti = rclient.multi()\n    projectBlockMulti.exists(keys.projectBlock({ project_id: projectId }))\n    projectBlockMulti.sadd(keys.docsInProject({ project_id: projectId }), docId)\n    const reply = await projectBlockMulti.exec()\n    const projectBlocked = reply[0] === 1\n    if (projectBlocked) {\n      // We don't clean up the spurious docId added in the docsInProject\n      // set. There is a risk that the docId was successfully added by a\n      // concurrent process.  This set is used when unloading projects. An\n      // extra docId will not prevent the project from being uploaded, but\n      // a missing docId means that the doc might stay in Redis forever.\n      throw new OError('Project blocked from loading docs', { projectId })\n    }\n\n    await RedisManager.setHistoryRangesSupportFlag(docId, historyRangesSupport)\n\n    if (!pathname) {\n      metrics.inc('pathname', 1, {\n        path: 'RedisManager.setDoc',\n        status: pathname === '' ? 'zero-length' : 'undefined',\n      })\n    }\n\n    // Make sure that this MULTI operation only operates on doc\n    // specific keys, i.e. keys that have the doc id in curly braces.\n    // The curly braces identify a hash key for Redis and ensures that\n    // the MULTI's operations are all done on the same node in a\n    // cluster environment.\n    const multi = rclient.multi()\n    multi.mset({","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/overleaf/overleaf/blob/28ad3b03b71cb4311decdcb55c36b33ec10d72db/services/document-updater/app/js/RedisManager.js#L68-L104","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Wait for the block TTL to expire and retry loading the project","Clear the project block key in Redis if it is stale (rclient DEL the block key) after verifying the project is healthy","Investigate why the project got blocked (too many docs / memory pressure) and reduce doc count or size","Check for retry storms from web hammering loadDoc and add backoff"],"exampleFix":"try {\n  await documentUpdaterHandler.promises.flushProjectToMongo(projectId)\n} catch (err) {\n  if (err.message === 'Project blocked from loading docs') {\n    await timer(30_000) // let the block expire\n    return retry()\n  }\n  throw err\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await putDocInMemory(...)\n} catch (err) {\n  if (err.message === 'Project blocked from loading docs') return retryAfterBlockExpiry(projectId)\n  throw err\n}","preventionTips":["Throttle concurrent project loads to avoid triggering the block","Check the project block key in Redis before bulk loads","Investigate root causes (project size, doc count) that lead to blocking","Use backoff, not tight retry loops, or the block will persist"],"tags":["document-updater","project-blocked","redis"],"backgroundTag":"project-blocked-from-loading","analyzedSha":"28ad3b03b71cb4311decdcb55c36b33ec10d72db","analyzedAt":"2026-09-03T02:10:22.807Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T07:17:11.731Z"}