microsoft/typescript-go · error · 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

Thrown by API.runWithTemporaryFileUpdate when baseSnapshot is no longer in the API's activeSnapshots set or reports isDisposed(). Snapshots leave the active set via snapshot.dispose() - explicit calls, API.close() disposing every active snapshot, or temporary snapshots disposed automatically in the runWithTemporaryFileUpdate finally block. The guard prevents sending updateTemporarySnapshot for a server-side snapshot that has already been released.

Source

Thrown at _packages/native-preview/src/api/async/api.ts:288

        }
        // Release the latest snapshot's cache refs if still held
        if (this.latestSnapshot) {
            this.sourceFileCache.releaseSnapshot(this.latestSnapshot.id);
            this.latestSnapshot = undefined;
        }
        await this.client.close();
        this.sourceFileCache.clear();
    }

    clearSourceFileCache(): void {
        this.sourceFileCache.clear();
    }

    async runWithTemporaryFileUpdate(baseSnapshot: Snapshot, file: DocumentIdentifier, newText: string, cb: (newSnapshot: Snapshot) => void | Promise<void>): Promise<void> {
        await this.ensureInitialized();

        if (!this.activeSnapshots.has(baseSnapshot) || baseSnapshot.isDisposed()) {
            throw new Error("Cannot run a temporary file update on an inactive snapshot");
        }
        const data = await 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

  1. Always base temporary updates on the freshest snapshot: call updateSnapshot(...) and use its return value immediately
  2. Check baseSnapshot.isDisposed() (public API) before calling, and stop caching snapshots across updates
  3. Do not use snapshots after API.close() or after their dispose() - reacquire from the API
  4. Only pass snapshots created by the same API instance

Example fix

// before
const snap = await api.updateSnapshot(); // ... later, after another update/dispose
await api.runWithTemporaryFileUpdate(snap, file, text, cb); // throws

// after
const snap = await api.updateSnapshot(); // freshest state, same tick
if (snap.isDisposed()) throw new Error('snapshot went stale');
await api.runWithTemporaryFileUpdate(snap, file, text, cb);
Defensive patterns

Strategy: validation

Validate before calling

// Public guard: only base updates on fresh, undisposed snapshots
if (baseSnapshot.isDisposed()) {
    throw new Error('base snapshot is disposed - call updateSnapshot() to get a fresh one');
}
await api.runWithTemporaryFileUpdate(baseSnapshot, file, newText, cb);

Try / catch

try {
    await api.runWithTemporaryFileUpdate(snap, file, text, cb);
} catch (e) {
    if (e instanceof Error && e.message.includes('inactive snapshot')) {
        snap = await api.updateSnapshot(); // refresh and retry once
        await api.runWithTemporaryFileUpdate(snap, file, text, cb);
    } else throw e;
}

Prevention

When it happens

Trigger: Reusing a temporary snapshot after its callback completed (auto-disposed in finally); passing a snapshot explicitly disposed earlier; calling after API.close(); passing a Snapshot obtained from a different API instance (never in this instance's activeSnapshots set).

Common situations: Caching a Snapshot across editor changes and then attempting a quick-fix/organize-imports temporary update on the stale one; nesting temporary updates where the outer callback's snapshot is used after await points that disposed it; integration tests that keep one snapshot for the whole run.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/0872ef540e74e99e. Report an issue: GitHub.