microsoft/typescript-go · error
Cannot run a temporary file update on an inactive snapshot
Error message
Cannot run a temporary file update on an inactive snapshot
What it means
runWithTemporaryFileUpdate applies a text edit to an existing Snapshot and returns a temporary Snapshot for queries like 'what would quickinfo look like with this edit'. The base snapshot must be live: still registered in the API's activeSnapshots set and not disposed. Using a stale, disposed, or foreign snapshot would compute results against server state that no longer exists, so the API throws up front.
Source
Thrown at _packages/native-preview/src/api/sync/api.ts:296
}
// Release the latest snapshot's cache refs if still held
if (this.latestSnapshot) {
this.sourceFileCache.releaseSnapshot(this.latestSnapshot.id);
this.latestSnapshot = undefined;
}
this.client.close();
this.sourceFileCache.clear();
}
clearSourceFileCache(): void {
this.sourceFileCache.clear();
}
runWithTemporaryFileUpdate(baseSnapshot: Snapshot, file: DocumentIdentifier, newText: string, cb: (newSnapshot: Snapshot) => void): void {
this.ensureInitialized();
if (!this.activeSnapshots.has(baseSnapshot) || baseSnapshot.isDisposed()) {
throw new Error("Cannot run a temporary file update on an inactive snapshot");
}
const data = this.client.apiRequest<UpdateSnapshotResponse>("updateTemporarySnapshot", { snapshot: baseSnapshot.id, file, newText });
// Retain cached source files from the base snapshot for files unchanged by
// the temporary update. The temporary snapshot is not the latest snapshot, so
// we never release the latest snapshot's cache here.
this.sourceFileCache.retainForSnapshot(data.snapshot, baseSnapshot.id, data.changes);
const snapshot = new Snapshot(
data,
this.client,
this.sourceFileCache,
this.toPath!,
() => {
this.activeSnapshots.delete(snapshot);
this.sourceFileCache.releaseSnapshot(snapshot.id);
},
);
View on GitHub (pinned to 1bcfa18d79)
Solutions
- Always derive temporary updates from the most recent snapshot returned by the API
- Check snapshot.isDisposed() before use and re-acquire a fresh snapshot if true
- Ensure only one owner disposes a snapshot; don't reuse snapshots across API.close() boundaries
Example fix
// before
const snap = api.getProjectSnapshot(p);
/* ... later, after dispose */
api.runWithTemporaryFileUpdate(snap, file, newText, cb); // throws
// after
if (snap.isDisposed()) throw new Error("stale snapshot");
api.runWithTemporaryFileUpdate(snap, file, newText, cb); Defensive patterns
Strategy: validation
Validate before calling
const canRunTempUpdate = (api: API, snap: Snapshot) => !snap.isDisposed() && /* snap obtained from this api and not yet replaced */ true;
Try / catch
try { api.runWithTemporaryFileUpdate(snap, file, text, cb); } catch (e) { if ((e as Error).message.includes("inactive snapshot")) { snap = api.getProjectSnapshot(cfg); api.runWithTemporaryFileUpdate(snap, file, text, cb); } else throw e; } Prevention
- Always base temporary updates on the snapshot most recently returned by the API
- Check isDisposed() before every runWithTemporaryFileUpdate
- Do not share snapshots across API instances or across close() boundaries
When it happens
Trigger: Calling api.runWithTemporaryFileUpdate(snapshot, ...) after snapshot.dispose(); after api.close() (which clears activeSnapshots); passing a Snapshot obtained from a different API instance; holding a snapshot across project reloads until the server released it.
Common situations: Caching snapshots for reuse in language services; async races where one code path disposes a snapshot while another still uses it; editor integration keeping an old snapshot after a didChange cycle invalidated it.
Related errors
- Cannot run a temporary file update on an inactive snapshot
- Snapshot is disposed
- Snapshot is disposed
- SyncRpcChannel is closed
- %w: symbol handle %d not found in snapshot registry
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/b3c42f478fd973ae.
Report an issue: GitHub.