microsoft/typescript-go · error · ErrClientError
%w: could not read file %q
Error message
%w: could not read file %q
What it means
parseConfigFile could not read the tsconfig file from the server filesystem: FS().ReadFile returned !ok after normalizing params.File against the session's current directory. It means the file does not exist at the resolved absolute path, is unreadable, or the DocumentIdentifier's uri/fileName form resolves differently than the caller assumed.
Source
Thrown at internal/api/session.go:1208
parsedCommandLine := tsoptions.ParseJsonConfigFileContent(
jsonValueToAny(params.JSON),
s.projectSession,
basePath,
nil, /*existingOptions*/
configFileName,
nil, /*resolutionStack*/
nil, /*extraFileExtensions*/
nil, /*extendedConfigCache*/
)
return NewConfigFileResponse(parsedCommandLine), nil
}
// handleParseConfigFile parses a tsconfig.json file and returns its contents.
func (s *Session) handleParseConfigFile(ctx context.Context, params *ParseConfigFileParams) (*ConfigFileResponse, error) {
configFileName := params.File.ToAbsoluteFileName(s.projectSession.GetCurrentDirectory())
configFileContent, ok := s.projectSession.FS().ReadFile(configFileName)
if !ok {
return nil, fmt.Errorf("%w: could not read file %q", ErrClientError, configFileName)
}
configDir := tspath.GetDirectoryPath(configFileName)
tsConfigSourceFile := tsoptions.NewTsconfigSourceFileFromFilePath(
configFileName,
s.toPath(configFileName),
configFileContent,
)
parsedCommandLine := tsoptions.ParseJsonSourceFileConfigFileContent(
tsConfigSourceFile,
s.projectSession,
configDir,
nil, /*existingOptions*/
nil, /*existingOptionsRaw*/
configFileName,
nil, /*resolutionStack*/
nil, /*extraFileExtensions*/
nil, /*extendedConfigCache*/View on GitHub (pinned to 1bcfa18d79)
Solutions
- Pass an absolute, normalized path in the file field
- Verify the file exists from the server process's view before calling
- Confirm the cwd the session was created with (it drives relative-path normalization) and send absolute paths to avoid depending on it
Example fix
// before
parseConfigFile({file: "tsconfig.json"}) // relative; depends on server cwd
// after
parseConfigFile({file: "/abs/path/to/project/tsconfig.json"}) Defensive patterns
Strategy: validation
Validate before calling
func readableConfig(absPath string) bool {
if !filepath.IsAbs(absPath) { return false }
info, err := os.Stat(absPath)
return err == nil && !info.IsDir()
}
// Note: the server stats this from ITS filesystem; verify from the same host/user when possible. Type guard
func isAbsoluteFile(p string) bool { return filepath.IsAbs(p) } Try / catch
if err != nil && strings.Contains(err.Error(), "could not read file") {
return fmt.Errorf("tsconfig not readable by server: %q (check path, case, permissions)", cfgPath)
} Prevention
- Send absolute, correctly-cased paths for config files
- Confirm the server process's view of the filesystem (same container/mounts) before blaming the path
- Check the session cwd used for normalization; absolute paths make it irrelevant
When it happens
Trigger: Passing a relative file name that normalizes against a different server cwd than expected; a URI whose FileName() form differs by case or separators from the on-disk path; the config file deleted or not checked out; permission denied on the file.
Common situations: Client and server in different working directories or containers; Windows path casing/separator mismatches; sparse checkouts missing the config; symlinks pointing outside the visible FS.
Related errors
- %w: exactly one of configDirectory or configFileName is requ
- Cannot create directory: a file already exists at "/${segmen
- Invalid file path: "${path}"
- %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/5b3757ab1007d4a8.
Report an issue: GitHub.