{"record":{"id":"b3c42f478fd973ae","repo":"microsoft/typescript-go","slug":"cannot-run-a-temporary-file-update-on-an-inactive-b3c42f","errorCode":null,"errorMessage":"Cannot run a temporary file update on an inactive snapshot","messagePattern":"Cannot run a temporary file update on an inactive snapshot","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"_packages/native-preview/src/api/sync/api.ts","lineNumber":296,"sourceCode":"        }\r\n        // Release the latest snapshot's cache refs if still held\r\n        if (this.latestSnapshot) {\r\n            this.sourceFileCache.releaseSnapshot(this.latestSnapshot.id);\r\n            this.latestSnapshot = undefined;\r\n        }\r\n        this.client.close();\r\n        this.sourceFileCache.clear();\r\n    }\r\n\r\n    clearSourceFileCache(): void {\r\n        this.sourceFileCache.clear();\r\n    }\r\n\r\n    runWithTemporaryFileUpdate(baseSnapshot: Snapshot, file: DocumentIdentifier, newText: string, cb: (newSnapshot: Snapshot) => void): void {\r\n        this.ensureInitialized();\r\n\r\n        if (!this.activeSnapshots.has(baseSnapshot) || baseSnapshot.isDisposed()) {\r\n            throw new Error(\"Cannot run a temporary file update on an inactive snapshot\");\r\n        }\r\n        const data = this.client.apiRequest<UpdateSnapshotResponse>(\"updateTemporarySnapshot\", { snapshot: baseSnapshot.id, file, newText });\r\n\r\n        // Retain cached source files from the base snapshot for files unchanged by\r\n        // the temporary update. The temporary snapshot is not the latest snapshot, so\r\n        // we never release the latest snapshot's cache here.\r\n        this.sourceFileCache.retainForSnapshot(data.snapshot, baseSnapshot.id, data.changes);\r\n\r\n        const snapshot = new Snapshot(\r\n            data,\r\n            this.client,\r\n            this.sourceFileCache,\r\n            this.toPath!,\r\n            () => {\r\n                this.activeSnapshots.delete(snapshot);\r\n                this.sourceFileCache.releaseSnapshot(snapshot.id);\r\n            },\r\n        );\r","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/_packages/native-preview/src/api/sync/api.ts#L278-L314","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst snap = api.getProjectSnapshot(p);\n/* ... later, after dispose */\napi.runWithTemporaryFileUpdate(snap, file, newText, cb); // throws\n\n// after\nif (snap.isDisposed()) throw new Error(\"stale snapshot\");\napi.runWithTemporaryFileUpdate(snap, file, newText, cb);","handlingStrategy":"validation","validationCode":"const canRunTempUpdate = (api: API, snap: Snapshot) =>\n  !snap.isDisposed() && /* snap obtained from this api and not yet replaced */ true;","typeGuard":null,"tryCatchPattern":"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; }","preventionTips":["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"],"tags":["typescript","snapshot","api","lifecycle"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}