microsoft/typescript-go · error · ErrClientError
%w: exactly one of configDirectory or configFileName is requ
Error message
%w: exactly one of configDirectory or configFileName is required
What it means
parseJsonConfigFileContent requires exactly one of configDirectory (string) and configFileName (DocumentIdentifier) to locate the in-memory JSON config; the handler enforces XOR and rejects both-set and neither-set. The chosen value determines the base path used to resolve relative file names inside the config.
Source
Thrown at internal/api/session.go:1178
}, nil
}
config, parseErrors := tsoptions.ParseConfigFileTextToJson(
configFileName,
s.toPath(configFileName),
configFileContent,
)
response := &ReadConfigFileResponse{Config: config}
if len(parseErrors) > 0 {
response.Error = NewDiagnosticResponse(parseErrors[0])
}
return response, nil
}
// handleParseJsonConfigFileContent parses an in-memory JSON configuration.
func (s *Session) handleParseJsonConfigFileContent(ctx context.Context, params *ParseJsonConfigFileContentParams) (*ConfigFileResponse, error) {
if (params.ConfigDirectory == nil) == (params.ConfigFileName == nil) {
return nil, fmt.Errorf("%w: exactly one of configDirectory or configFileName is required", ErrClientError)
}
var basePath string
var configFileName string
if params.ConfigDirectory != nil {
basePath = tspath.GetNormalizedAbsolutePath(*params.ConfigDirectory, s.projectSession.GetCurrentDirectory())
} else {
configFileName = params.ConfigFileName.ToAbsoluteFileName(s.projectSession.GetCurrentDirectory())
basePath = tspath.GetDirectoryPath(configFileName)
}
parsedCommandLine := tsoptions.ParseJsonConfigFileContent(
jsonValueToAny(params.JSON),
s.projectSession,
basePath,
nil, /*existingOptions*/
configFileName,
nil, /*resolutionStack*/View on GitHub (pinned to 1bcfa18d79)
Solutions
- Decide which anchor you need: configDirectory to resolve a config body against a folder, or configFileName when the JSON came from a named file
- Send exactly one of the two fields and omit the other entirely
Example fix
// before
params := {json: cfg, configDirectory: "/proj", configFileName: {uri: "file:///proj/tsconfig.json"}}
// after
params := {json: cfg, configDirectory: "/proj"} Defensive patterns
Strategy: validation
Validate before calling
func buildConfigParams(jsonBody packagejson.JSONValue, dir string) (api.ParseJsonConfigFileContentParams, error) {
p := api.ParseJsonConfigFileContentParams{JSON: jsonBody}
if dir != "" {
p.ConfigDirectory = &dir
return p, nil
}
return p, fmt.Errorf("configDirectory or configFileName required")
}
// XOR check mirrors the server: (ConfigDirectory == nil) != (ConfigFileName == nil) Type guard
func validConfigAnchor(p *api.ParseJsonConfigFileContentParams) bool {
if p == nil { return false }
return (p.ConfigDirectory == nil) != (p.ConfigFileName == nil)
} Prevention
- Decide up front whether you anchor the config at a directory or a named file, and send only that field
- Add a unit test asserting exactly one of the two pointers is set before each call
When it happens
Trigger: Sending both fields; sending neither (e.g. both null or the whole object omitted); client serialization that always emits both keys with defaults.
Common situations: Porting from the classic tsserver API where only a directory was needed; JSON built from a struct with both fields populated; omitempty left off so empty strings/objects still count as present on the wire only when non-nil pointers are set.
Related errors
- %w: could not read file %q
- Cannot run a temporary file update on an inactive snapshot
- Snapshot is disposed
- Cannot create directory: a file already exists at "/${segmen
- Invalid file path: "${path}"
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/84389eb8fc2370ea.
Report an issue: GitHub.