microsoft/typescript-go · error · ErrClientError
%w: failed to update snapshot: %w
Error message
%w: failed to update snapshot: %w
What it means
updateSnapshot failed inside projectSession.APIUpdate, and the error is wrapped in ErrClientError even though causes can be environmental: unreadable or invalid tsconfig for an opened project, filesystem errors while loading files, or a canceled context. The server correctly Derefs the snapshot it still returns on the error path, so no client-side cleanup of a snapshot handle is needed for the failed call.
Source
Thrown at internal/api/session.go:995
if !s.openFiles.Has(path) {
continue
}
if apiRequest.CloseFiles == nil {
apiRequest.CloseFiles = collections.NewSetWithSizeHint[tspath.Path](len(params.CloseFiles))
}
apiRequest.CloseFiles.Add(path)
closedFiles = append(closedFiles, path)
}
// Even when nothing is opened or closed, APIUpdate ensures all projects and
// files opened by the API are up to date. For an API connected to an LSP server,
// this brings the API state up to date with the LSP state and ensures projects
// the API cares about are ready to be queried.
snapshot, err := s.projectSession.APIUpdate(ctx, fileChanges, apiRequest)
if err != nil {
// APIUpdate returns a ref'd snapshot even on error; release it.
snapshot.Deref(s.projectSession)
return nil, fmt.Errorf("%w: failed to update snapshot: %w", ErrClientError, err)
}
// Commit ref tracking now that the update succeeded.
for _, configPath := range openedProjects {
s.openProjects.Add(configPath)
}
for _, configPath := range closedProjects {
s.openProjects.Delete(configPath)
}
for _, path := range openedFiles {
s.openFiles.Add(path)
}
for _, path := range closedFiles {
s.openFiles.Delete(path)
}
// Create or ref-count snapshot data, then atomically read the previous latest
// snapshot (the diff base) and advance latestSnapshot to the new handle.View on GitHub (pinned to 1bcfa18d79)
Solutions
- Inspect the wrapped error text to distinguish config/FS problems from cancellation
- Pre-validate the config with parseConfigFile/readConfigFile before opening the project
- For deadline cancellations, raise or remove the client timeout and retry the update
- Retry once after the filesystem condition is fixed; updateSnapshot is idempotent
Example fix
// before ctx, cancel := context.WithTimeout(ctx, 500*time.Millisecond) // too tight for big projects resp, err := updateSnapshot(ctx, changes) // after ctx, cancel := context.WithTimeout(ctx, 60*time.Second) resp, err := updateSnapshot(ctx, changes)
Defensive patterns
Strategy: retry
Validate before calling
// Pre-validate configs of projects you are about to open.
for _, cfg := range projectsToOpen {
if _, err := parseConfigFile(ctx, api.ParseConfigFileParams{File: api.DocumentIdentifier{FileName: cfg}}); err != nil {
return fmt.Errorf("bad config %s: %w", cfg, err)
}
} Try / catch
resp, err := updateSnapshot(ctx, changes)
if err != nil {
if ctx.Err() != nil || errors.Is(err, context.DeadlineExceeded) {
// cancellation: retry with a longer deadline; updateSnapshot is idempotent
resp, err = updateSnapshot(ctxLonger, changes)
}
if err != nil { return err } // config/FS problem: inspect wrapped error
} Prevention
- Give updateSnapshot deadlines sized to project size (large monorepos need seconds-to-minutes)
- Validate tsconfig files before opening their projects
- Do not delete or move workspace files concurrently with snapshot updates
When it happens
Trigger: Opening a project whose tsconfig.json references unreadable files or contains invalid JSON; a context deadline hit while a large project loads; files disappearing mid-update; FS access errors from the host filesystem or overlay.
Common situations: Configs valid on the dev machine but broken in CI (missing node_modules, different case in imports); very large monorepos exceeding an aggressive client timeout; files deleted concurrently with the update.
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 start CPU profile: %w
- %w: failed to save heap profile: %w
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/f230bd58931defe0.
Report an issue: GitHub.