microsoft/typescript-go · error · ErrClientError
%w: failed to start CPU profile: %w
Error message
%w: failed to start CPU profile: %w
What it means
startCPUProfile forwarded the underlying profiler error, wrapped in ErrClientError. The wrapped error comes from the cpuProfiler: most commonly Go's pprof "CPU profiling already in progress" when a previous profile was never stopped, or a file-creation failure because dir does not exist or is not writable by the server process.
Source
Thrown at internal/api/session.go:874
case string(MethodGetReferencesToSymbolInFile):
return s.handleGetReferencesToSymbolInFile(ctx, parsed.(*GetReferencesToSymbolInFileParams))
case string(MethodGetReferencedSymbolsForNode):
return s.handleGetReferencedSymbolsForNode(ctx, parsed.(*GetReferencedSymbolsForNodeParams))
case string(MethodGetSignatureUsages):
return s.handleGetSignatureUsages(ctx, parsed.(*GetSignatureUsagesParams))
case string(MethodGetCompletionsAtPosition):
return s.handleGetCompletionsAtPosition(ctx, parsed.(*GetCompletionsAtPositionParams))
default:
return nil, fmt.Errorf("unknown method: %s", method)
}
}
func (s *Session) handleStartCPUProfile(_ context.Context, params *ProfileParams) (any, error) {
if params == nil || params.Dir == "" {
return nil, fmt.Errorf("%w: dir is required", ErrClientError)
}
if err := s.cpuProfiler.StartCPUProfile(params.Dir); err != nil {
return nil, fmt.Errorf("%w: failed to start CPU profile: %w", ErrClientError, err)
}
return nil, nil
}
func (s *Session) handleStopCPUProfile(_ context.Context) (*ProfileResult, error) {
filePath, err := s.cpuProfiler.StopCPUProfile()
if err != nil {
return nil, fmt.Errorf("%w: failed to stop CPU profile: %w", ErrClientError, err)
}
return &ProfileResult{File: filePath}, nil
}
func (s *Session) handleSaveHeapProfile(_ context.Context, params *ProfileParams) (*ProfileResult, error) {
if params == nil || params.Dir == "" {
return nil, fmt.Errorf("%w: dir is required", ErrClientError)
}
filePath, err := pprof.SaveHeapProfile(params.Dir)
if err != nil {View on GitHub (pinned to 1bcfa18d79)
Solutions
- If a profile may already be running, call stopCPUProfile first (ignore its error) before starting again
- Ensure dir exists and is writable by the server process (mkdir -p, check ownership/permissions)
- Use an absolute path to avoid surprises from the server's working directory
Example fix
// before
start(dir) // may hit "already in progress"
// after
if _, err := stop(); err != nil { /* no active profile; ignore */ }
if err := start(dir); err != nil { return err } Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: create the dir and prove it is writable by the server user.
if err := os.MkdirAll(dir, 0o755); err != nil { return err }
probe := filepath.Join(dir, ".writeprobe")
if err := os.WriteFile(probe, nil, 0o644); err != nil { return err }
os.Remove(probe) Try / catch
if err != nil {
msg := err.Error()
switch {
case strings.Contains(msg, "already in progress"):
_, _ = session.HandleRequest(ctx, string(api.MethodStopCPUProfile), nil) // reset, then retry once
case strings.Contains(msg, "permission") || strings.Contains(msg, "no such file"):
return fmt.Errorf("profile dir not writable: %s", dir)
}
return err
} Prevention
- Guard start with a client-side 'profiling' flag set on success and cleared on stop
- mkdir -p the output directory in deployment before enabling profiling
- On start failure, stop any stale profile before retrying
When it happens
Trigger: Calling startCPUProfile twice without an intervening stopCPUProfile; passing a dir that was never created; running the server under a user without write permission to dir; read-only container filesystems.
Common situations: Profiler lifecycle managed in separate code paths (start on demand, stop on shutdown) that can double-start; orchestrators mounting output dirs read-only; missing mkdir step in deployment scripts.
Related errors
- %w: dir is required
- %w: failed to stop CPU profile: %w
- %w: failed to save heap profile: %w
- %w: failed to update snapshot: %w
- %w: could not read file %q
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/4a811f1126824702.
Report an issue: GitHub.