overleaf/overleaf · error · OError
unrecognised file: not in snapshot
Error message
unrecognised file: not in snapshot
What it means
expandResyncDocContentUpdate resolves the doc's pathname via UpdateTranslator._convertPathname and looks it up in this.files (the snapshot's file map). If no entry exists, the resync expects content for a file the snapshot does not know about, so it throws OError('unrecognised file: not in snapshot') — the snapshot and the resync request are inconsistent.
Source
Thrown at services/project-history/app/js/SyncManager.js:895
Metrics.inc('project_history_resync_operation', 1, {
status: 'update binary file contents',
})
}
}
/**
* Expand a resyncDocContentUpdate
*
* @param {ResyncDocContentUpdate} update
*/
async expandResyncDocContentUpdate(update) {
const pathname = UpdateTranslator._convertPathname(update.path)
const snapshotFile = this.files[pathname]
const expectedFile = update.resyncDocContent
const expectedContent = expectedFile.content
if (!snapshotFile) {
throw new OError('unrecognised file: not in snapshot')
}
// Compare hashes to see if the persisted file matches the expected content.
// The hash of the persisted files is stored in the snapshot.
// Note getHash() returns the hash only when the persisted file has
// no changes in the snapshot, the hash is null if there are changes
// that apply to it.
let hashesMatch = false
const persistedHash = snapshotFile.getHash()
if (persistedHash != null) {
const expectedHash = HashManager._getBlobHashFromString(expectedContent)
if (persistedHash === expectedHash) {
logger.debug(
{ projectId: this.projectId, persistedHash, expectedHash },
'skipping diff because hashes match and persisted file has no ops'
)
hashesMatch = true
}View on GitHub (pinned to 28ad3b03b7)
Solutions
- Reload the snapshot for the current historyId so it includes the file
- Skip doc-content resync for deleted files, or re-run a full project-structure resync to realign snapshot and expectations
- Verify path conversion matches how the snapshot keys files (UpdateTranslator._convertPathname vs raw path)
- Ensure resync start and update processing use the same project version/history snapshot
Example fix
// before
const snapshotFile = this.files[pathname]
if (!snapshotFile) throw new OError('unrecognised file: not in snapshot')
// after: tolerate files removed since resync started
const snapshotFile = this.files[pathname]
if (!snapshotFile) {
logger.warn({ projectId: this.projectId, pathname }, 'file gone from snapshot; skipping resync')
return []
} Defensive patterns
Strategy: validation
Validate before calling
const pathname = UpdateTranslator._convertPathname(update.path)
if (!snapshot.files[pathname]) { logger.warn({ path: update.path }, 'file absent from snapshot; skipping doc resync'); return } Type guard
function fileInSnapshot(files, pathname) { return files != null && Object.prototype.hasOwnProperty.call(files, pathname) } Try / catch
try { await expandResync(update) } catch (err) { if (err instanceof OError && err.message === 'unrecognised file: not in snapshot') { await reloadSnapshotForCurrentHistoryId(); return expandResync(update) } throw err } Prevention
- Keep resync initiation and processing on the same historyId/snapshot
- Re-run full structure resync after renames/deletes
- Log pathname conversions to catch path-normalization drift
When it happens
Trigger: A resyncDocContent update references update.path that, after pathname conversion, is absent from the snapshot's files map — e.g. the file was deleted, renamed, or the snapshot was loaded for the wrong historyId.
Common situations: File renamed/deleted between resync initiation and processing; resync run against a stale snapshot (older historyId); case-sensitivity or pathname-conversion differences between web and history services.
Related errors
- Operation can't retain more chars than are left in the strin
- can't find file for editing: ${pathname}
- missing updates
- blocking resync doc content insert into project history queu
- The op is too long for this document
AI-assisted analysis of overleaf/overleaf@28ad3b03b7 (2026-09-03).
Data as JSON: /api/errors/14ef526c1416ef1d.
Report an issue: GitHub.