microsoft/typescript-go · error · ErrClientError
%w: failed to update temporary snapshot: %w
Error message
%w: failed to update temporary snapshot: %w
What it means
updateTemporarySnapshot failed inside projectSession.APIUpdateTemporary, wrapped in ErrClientError. This call builds a scratch snapshot by applying params.NewText at the given file URI on top of the base snapshot; it fails when the base snapshot does not contain the file/project state needed (e.g. the file was never opened into that snapshot) or when the context is canceled.
Source
Thrown at internal/api/session.go:1075
Changes: changes,
}, nil
}
// handleUpdateTemporarySnapshot creates a temporary snapshot that overrides the
// content of a single file, without opening/closing any projects or files and
// without advancing the session's latest snapshot.
func (s *Session) handleUpdateTemporarySnapshot(ctx context.Context, params *UpdateTemporarySnapshotParams) (*UpdateSnapshotResponse, error) {
baseSD, err := s.retainSnapshotData(params.Snapshot)
if err != nil {
return nil, err
}
defer func() { _ = s.releaseSnapshot(params.Snapshot) }()
uri := params.File.ToURI(s.projectSession.GetCurrentDirectory())
snapshot, err := s.projectSession.APIUpdateTemporary(ctx, baseSD.snapshot, uri, params.NewText)
if err != nil {
return nil, fmt.Errorf("%w: failed to update temporary snapshot: %w", ErrClientError, err)
}
handle := snapshotHandle(snapshot)
s.snapshotsMu.Lock()
sd, exists := s.snapshots[handle]
if exists {
snapshot.Deref(s.projectSession)
sd.refCount++
} else {
sd = &snapshotData{
snapshot: snapshot,
refCount: 1,
symbolRegistry: make(map[SymbolID]*ast.Symbol),
symbolCanonicalProjects: make(map[SymbolID]ProjectID),
projectRegistries: make(map[ProjectID]*projectRegistryData),
}
s.snapshots[handle] = sd
}View on GitHub (pinned to 1bcfa18d79)
Solutions
- Ensure the target file was opened (openedFiles) in an updateSnapshot and use the handle from that response as params.Snapshot
- Do not reuse snapshot handles after calling release on them
- Retry with a fresh updateSnapshot if the editor reopens the file
Example fix
// before updateSnapshot(ctx, changes) // changes does NOT include the file updateTemporarySnapshot(base, file, newText) // fails // after resp, _ := updateSnapshot(ctx, changesWithFileOpened) updateTemporarySnapshot(resp.Snapshot, file, newText)
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the file is open in the base snapshot before a temporary update.
opened := false
for _, f := range lastUpdateResponse.Changes /* or your tracked openedFiles */ {
if f == targetFile { opened = true }
}
if !opened {
resp, err := updateSnapshot(ctx, openFile(targetFile))
if err != nil { return err }
baseSnapshot = resp.Snapshot
} Type guard
func canUpdateTemporary(base api.SnapshotID, baseValid bool, fileOpened bool) bool {
return base != 0 && baseValid && fileOpened
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "temporary snapshot") {
// re-open the file via updateSnapshot, then retry with the fresh handle
}
return err
} Prevention
- Model open/close state client-side and mirror editor didOpen/didClose into updateSnapshot
- Always pair a temporary update with the handle from the update that opened the file
- Never call updateTemporarySnapshot with a handle you already released
When it happens
Trigger: Calling updateTemporarySnapshot for a file that was not passed via openedFiles in the base updateSnapshot; using a base snapshot handle that was already released or superseded; cancellation mid-reparse.
Common situations: Completion-style flows that send didChange-style text without a prior open; client state machines that reuse a stale snapshot after the editor closed and reopened the file.
Related errors
- Cannot run a temporary file update on an inactive snapshot
- Snapshot is disposed
- Cannot run a temporary file update on an inactive snapshot
- %w: failed to update snapshot: %w
- %w: empty handle
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/22d7e651a48ea2d9.
Report an issue: GitHub.