toeverything/AFFiNE · error
Can not find the version to rollback to.
Error message
Can not find the version to rollback to.
What it means
DocHistoryManager.rollbackDoc(docId, timestamp) first loads the historical snapshot via getHistory(docId, timestamp); when no history record exists for that doc at/before that timestamp, it throws 'Can not find the version to rollback to.' A rollback needs an actual stored snapshot to revert to — it cannot reconstruct one.
Solutions
- Verify the timestamp exists in history first: call listHistory(docId) and match against the entries the user actually sees.
- Use the exact timestamp from a ListedHistory entry rather than deriving/computing one.
- If the record was legitimately deleted/expired, surface 'version no longer available' — there is nothing to roll back to.
- Ensure the doc has been updated at least once after the target point, since history records are only created on update pushes.
Example fix
// before
await history.rollbackDoc(docId, pickedTimestamp);
// after
const list = await history.listHistory(docId);
const entry = list.find(h => h.timestamp.getTime() === pickedTimestamp.getTime());
if (!entry) {
toast('This version is no longer available.');
} else {
await history.rollbackDoc(docId, entry.timestamp);
} Defensive patterns
Strategy: validation
Validate before calling
const versions = await history.listHistory(docId);
const target = versions.find(v => v.timestamp.getTime() === chosen.getTime());
if (!target) throw new Error('version not available — refresh the history list');
await history.rollbackDoc(docId, target.timestamp); Type guard
const hasVersionAt = (list: ListedHistory[], ts: Date): boolean => list.some(v => v.timestamp.getTime() === ts.getTime());
Try / catch
try { await history.rollbackDoc(docId, ts); } catch (e) { if (e instanceof Error && e.message === 'Can not find the version to rollback to.') { /* refresh listHistory, show 'version unavailable' */ } throw e; } Prevention
- Drive rollback from timestamps returned by listHistory, never computed ones
- Refresh the history list right before rollback in long-open UIs
- Remember: history records only exist for updates — a never-updated doc has none
When it happens
Trigger: Calling rollbackDoc with a timestamp for which no history was ever created (histories are only created on update pushes — see the createHistory contract comment); passing a timestamp older than the earliest snapshot; history retention/expiration removed the record; timestamp precision mismatch (ms vs s) so no record matches.
Common situations: UI history panel showing a stale list after history records expired or were deleted (deleteHistory); rolling back a doc that was created but never updated (no snapshots); clock/timezone handling producing wrong timestamps; self-hosted server with history cleanup jobs pruning old snapshots.
Related errors
- Can not find the current version of the doc.
- doc_history_not_found
- doc_not_found
- 1
- a should be smaller than b
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/a66809db0af01b8c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/common/nbstore/src/storage/history.ts:79
abstract upsertDocSnapshot(
snapshot: DocRecord,
prevSnapshot: DocRecord | null
): Promise<boolean>;
abstract listHistories(
docId: string,
filter?: HistoryFilter
): Promise<ListedHistory[]>;
abstract getHistory(
docId: string,
timestamp: Date
): Promise<DocRecord | null>;
abstract deleteHistory(docId: string, timestamp: Date): Promise<void>;
async rollbackDoc(docId: string, timestamp: Date, editor?: string) {
const toSnapshot = await this.getHistory(docId, timestamp);
if (!toSnapshot) {
throw new Error('Can not find the version to rollback to.');
}
const fromSnapshot = await this.getDoc(docId);
if (!fromSnapshot) {
throw new Error('Can not find the current version of the doc.');
}
const change = this.generateRevertUpdate(fromSnapshot.bin, toSnapshot.bin);
await this.pushDocUpdate({ docId, bin: change, editor }, 'rollback');
// force create a new history record after rollback
await this.createHistory(docId, fromSnapshot);
}
// history can only be created upon update pushing.
protected abstract createHistory(
docId: string,
snapshot: DocRecordView on GitHub (pinned to b4c8548c09)