github/copilot-sdk · error · ArgumentException
CopilotClient is in Mode = CopilotClientMode.Empty but the…
Error message
CopilotClient is in Mode = CopilotClientMode.Empty but the session config did not specify AvailableTools. Empty mode requires every session to explicitly opt into the tools it wants — e.g. `AvailableTools = new ToolSet().AddBuiltIn(BuiltInTools.Isolated)`.
What it means
The CopilotClient constructor throws this ArgumentException when the client is in CopilotClientMode.Empty and a session config does not specify AvailableTools. Empty mode intentionally exposes zero tools by default; every session must explicitly opt in to the tools it wants, so a config without AvailableTools is rejected.
Solutions
- Set AvailableTools on the session config, e.g. AvailableTools = new ToolSet().AddBuiltIn(BuiltInTools.Isolated).
- Use a different CopilotClientMode if you don't need the strict empty-mode behavior.
- Update all shared/default session config factories used with the Empty-mode client.
Example fix
// before
var config = new SessionConfig(); // no AvailableTools
var session = await client.CreateSessionAsync(config); // throws in Empty mode
// after
var config = new SessionConfig { AvailableTools = new ToolSet().AddBuiltIn(BuiltInTools.Isolated) };
var session = await client.CreateSessionAsync(config); Defensive patterns
Strategy: validation
Validate before calling
if (mode == CopilotClientMode.Empty && sessionConfig.AvailableTools is null)
throw new ArgumentException("Empty mode requires AvailableTools on every session config."); Type guard
static bool IsValidForEmptyMode(CopilotClientMode mode, SessionConfigBase cfg) => mode != CopilotClientMode.Empty || cfg.AvailableTools is not null;
Try / catch
try { session = await client.CreateSessionAsync(config); }
catch (ArgumentException ex) when (ex.Message.Contains("CopilotClientMode.Empty")) { config.AvailableTools ??= new ToolSet().AddBuiltIn(BuiltInTools.Isolated); session = await client.CreateSessionAsync(config); } Prevention
- Always set AvailableTools in shared session config factories when using Empty mode
- Encode the empty-mode requirement in your config builder API
- Add a test that creates a session with every shipped config template
When it happens
Trigger: new CopilotClient(options with Mode = CopilotClientMode.Empty, ...) then calling CreateSessionAsync with a config whose AvailableTools is null. ValidateToolFilterList/Empty-mode check runs per session config.
Common situations: Switching the client to Empty mode for least-privilege but forgetting to update existing session configs; shared/default session configs written before the mode change; tests that create bare SessionConfig objects.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Invalid entry '*': there is no bare wildcard. Use `new…
- Unsupported RuntimeConnection type
- Client is in Mode=ModeEmpty but the session config did not…
- sessionFs.initialCwd is required
- sessionFs.sessionStatePath is required
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/aa511867e5930c00.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Client.cs:973
}
}
}
/// <summary>
/// Resolves <see cref="SessionConfigBase.AvailableTools"/> /
/// <see cref="SessionConfigBase.ExcludedTools"/> for the wire payload,
/// validating empty-mode requirements. <c>toolFilterPrecedence</c> is
/// always <c>excluded</c> so SDK consumers get composable allowlist /
/// denylist semantics.
/// </summary>
private (IList<string>? AvailableTools, IList<string>? ExcludedTools, OptionsUpdateToolFilterPrecedence ToolFilterPrecedence) ResolveToolFilterOptions(SessionConfigBase config)
{
ValidateToolFilterList(nameof(SessionConfigBase.AvailableTools), config.AvailableTools);
ValidateToolFilterList(nameof(SessionConfigBase.ExcludedTools), config.ExcludedTools);
if (_options.Mode == CopilotClientMode.Empty && config.AvailableTools is null)
{
throw new ArgumentException(
"CopilotClient is in Mode = CopilotClientMode.Empty but the session config did " +
"not specify AvailableTools. Empty mode requires every session to explicitly " +
"opt into the tools it wants — e.g. " +
"`AvailableTools = new ToolSet().AddBuiltIn(BuiltInTools.Isolated)`.",
nameof(config));
}
return (config.AvailableTools, config.ExcludedTools, OptionsUpdateToolFilterPrecedence.Excluded);
}
/// <summary>
/// Applies mode-specific defaults to a session config in place. Caller
/// values win — only fields left unset by the caller are filled in.
/// </summary>
private void ApplyConfigDefaultsForMode(SessionConfigBase config)
{
if (_options.Mode == CopilotClientMode.Empty)
{View on GitHub (pinned to cd8cf15dc3)