{"record":{"id":"c7f0889160c615ba","repo":"toeverything/AFFiNE","slug":"can-not-find-the-current-version-of-the-doc","errorCode":null,"errorMessage":"Can not find the current version of the doc.","messagePattern":"Can not find the current version of the doc\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/backend/server/src/core/doc/storage/doc.ts","lineNumber":254,"sourceCode":"\n  abstract deleteDoc(spaceId: string, docId: string): Promise<void>;\n  abstract deleteSpace(spaceId: string): Promise<void>;\n  async rollbackDoc(\n    spaceId: string,\n    docId: string,\n    timestamp: number,\n    editorId?: string\n  ): Promise<void> {\n    await using _lock = await this.lockDocForUpdate(spaceId, docId);\n    const toSnapshot = await this.getDocHistory(spaceId, docId, timestamp);\n    if (!toSnapshot) {\n      throw new Error('Can not find the version to rollback to.');\n    }\n\n    const fromSnapshot = await this.getDocSnapshot(spaceId, docId);\n\n    if (!fromSnapshot) {\n      throw new Error('Can not find the current version of the doc.');\n    }\n\n    const change = this.generateChangeUpdate(fromSnapshot.bin, toSnapshot.bin);\n    await this.pushDocUpdates(spaceId, docId, [change], editorId);\n    // force create a new history record after rollback\n    await this.createDocHistory(fromSnapshot, true);\n  }\n\n  abstract getSpaceDocTimestamps(\n    spaceId: string,\n    after?: number\n  ): Promise<Record<string, number> | null>;\n  abstract listDocHistories(\n    spaceId: string,\n    docId: string,\n    query: { skip?: number; limit?: number }\n  ): Promise<{ timestamp: number; editor: Editor | null }[]>;\n  abstract getDocHistory(","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/core/doc/storage/doc.ts#L236-L272","documentation":"Thrown during rollbackDoc when getDocSnapshot(spaceId, docId) returns no current snapshot. Even though the target history snapshot exists, the doc has no live 'current' bin to diff against, so generateChangeUpdate has nothing to compute from. This usually indicates the doc was deleted or never had its snapshot materialized.","triggerScenarios":"Rolling back a doc that has history rows but whose current snapshot row is missing (deleted doc, partially-migrated doc, snapshot table out of sync with history table). Also possible right after a deleteDoc that removed the snapshot but left orphaned history.","commonSituations":"Post-migration data inconsistency between snapshot and history tables. A doc that was soft/hard deleted while a rollback request was in flight. Storage backend (S3/DB) partial failure that wrote history but not the snapshot.","solutions":["Check whether the doc still exists via getDocSnapshot before offering rollback in the UI; hide the action if no current snapshot.","Reconcile the snapshot table with the history table for the affected docId (re-materialize the snapshot from the latest history).","If the doc was intentionally deleted, prevent rollback by filtering deleted docs out of the history browser.","Map to a typed NotFound/Conflict error and return 404/409 instead of a generic 500."],"exampleFix":"// before\nconst fromSnapshot = await this.getDocSnapshot(spaceId, docId);\nif (!fromSnapshot) {\n  throw new Error('Can not find the current version of the doc.');\n}\n\n// after\nconst fromSnapshot = await this.getDocSnapshot(spaceId, docId);\nif (!fromSnapshot) {\n  throw new ConflictException(\n    `Doc ${docId} has no current snapshot; cannot compute rollback delta`\n  );\n}","handlingStrategy":"validation","validationCode":"async function assertCurrentSnapshot(storage, ws, doc) {\n  const snap = await storage.getDocSnapshot(ws, doc);\n  if (!snap?.bin) {\n    throw new UserError(`Doc ${doc} has no current snapshot; rollback unavailable`);\n  }\n  return snap;\n}","typeGuard":"function isCurrentSnapshotMissing(e: unknown): boolean {\n  return e instanceof Error && e.message === 'Can not find the current version of the doc.';\n}","tryCatchPattern":"try {\n  await doc.rollbackDoc(ws, doc, ts);\n} catch (e) {\n  if (isCurrentSnapshotMissing(e)) {\n    return res.status(409).send('Doc snapshot missing; cannot roll back');\n  }\n  throw e;\n}","preventionTips":["Reconcile snapshot vs history tables during migrations.","Disable rollback UI for docs whose snapshot is missing.","Audit deleteDoc paths to ensure snapshots aren't orphaned from history."],"tags":["rollback","snapshot","doc","data-integrity","not-found"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}