{"record":{"id":"dbec9cc6cf5c4abb","repo":"microsoft/typescript-go","slug":"w-failed-to-save-heap-profile-w","errorCode":null,"errorMessage":"%w: failed to save heap profile: %w","messagePattern":"%w: failed to save heap profile: %w","errorType":"error_code","errorClass":"ErrClientError","httpStatus":null,"severity":"error","filePath":"internal/api/session.go","lineNumber":893,"sourceCode":"\t}\n\treturn nil, nil\n}\n\nfunc (s *Session) handleStopCPUProfile(_ context.Context) (*ProfileResult, error) {\n\tfilePath, err := s.cpuProfiler.StopCPUProfile()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: failed to stop CPU profile: %w\", ErrClientError, err)\n\t}\n\treturn &ProfileResult{File: filePath}, nil\n}\n\nfunc (s *Session) handleSaveHeapProfile(_ context.Context, params *ProfileParams) (*ProfileResult, error) {\n\tif params == nil || params.Dir == \"\" {\n\t\treturn nil, fmt.Errorf(\"%w: dir is required\", ErrClientError)\n\t}\n\tfilePath, err := pprof.SaveHeapProfile(params.Dir)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: failed to save heap profile: %w\", ErrClientError, err)\n\t}\n\treturn &ProfileResult{File: filePath}, nil\n}\n\n// HandleNotification implements Handler.\nfunc (s *Session) HandleNotification(ctx context.Context, method string, params json.Value) error {\n\t// TODO: Implement notification handling\n\treturn nil\n}\n\nfunc (s *Session) handleInitialize(ctx context.Context) (*InitializeResponse, error) {\n\treturn &InitializeResponse{\n\t\tUseCaseSensitiveFileNames: s.projectSession.FS().UseCaseSensitiveFileNames(),\n\t\tCurrentDirectory:          s.projectSession.GetCurrentDirectory(),\n\t}, nil\n}\n\n// handleUpdateSnapshot creates a new snapshot, optionally opening or closing","sourceCodeStart":875,"sourceCodeEnd":911,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/internal/api/session.go#L875-L911","documentation":"saveHeapProfile forwarded the error from pprof.SaveHeapProfile, wrapped in ErrClientError. SaveHeapProfile creates and writes a file under dir, so failures are file-creation or write failures: missing directory, permission denied, read-only filesystem, or disk full.","triggerScenarios":"Passing a dir that does not exist; server process lacking write permission to dir; disk exhaustion during the heap dump (heap profiles of large compile servers can be hundreds of MB); path pointing at a file instead of a directory.","commonSituations":"Profiling production containers with read-only layers; dirs created in a different mount namespace; disk pressure on CI runners.","solutions":["Create dir and verify writability before issuing the request (write a probe file from the server's user)","Free disk space or choose a volume with headroom comparable to server memory","Use an absolute path to avoid cwd-relative surprises"],"exampleFix":"// before\nsaveHeapProfile(\"profiles\") // relative, may not exist where the server resolves it\n\n// after\nos.MkdirAll(\"/data/tsprofiles\", 0o755)\nsaveHeapProfile(\"/data/tsprofiles\")","handlingStrategy":"validation","validationCode":"func ensureWritableDir(dir string) error {\n    if err := os.MkdirAll(dir, 0o755); err != nil { return err }\n    probe := filepath.Join(dir, \".probe\")\n    if err := os.WriteFile(probe, nil, 0o644); err != nil { return err }\n    return os.Remove(probe)\n}\n// Call ensureWritableDir(params.Dir) from the server's user context before saveHeapProfile.","typeGuard":null,"tryCatchPattern":"if _, err := session.HandleRequest(ctx, string(api.MethodSaveHeapProfile), params); err != nil {\n    if strings.Contains(err.Error(), \"heap profile\") {\n        // dir problem or disk full: check space and permissions, then retry once after fixing\n    }\n    return err\n}","preventionTips":["Pre-create and probe-writable the profile dir before requesting heap dumps","Ensure free disk at least the size of server RSS before heap profiling","Use an absolute path on a writable volume, not the container's read-only layer"],"tags":["profiling","heap-profile","filesystem","api"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}