github/copilot-sdk · error · ArgumentException
CopilotClient was created with Mode =…
Error message
CopilotClient was created with Mode = CopilotClientMode.Empty but neither BaseDirectory nor SessionFs was set. Empty mode requires an explicit per-session persistence location; pick one.
What it means
CopilotClientMode.Empty requires an explicit per-session persistence location: BaseDirectory or SessionFs on the options, or an external UriRuntimeConnection (which manages its own persistence). The constructor throws ArgumentException when Empty mode is selected without any of these.
Solutions
- Set options.BaseDirectory to a directory for per-session persistence
- Set options.SessionFs to a session filesystem implementation
- Or use an external runtime via RuntimeConnection.ForUri which manages persistence itself, or choose a non-Empty mode
Example fix
// before
var options = new CopilotClientOptions { Mode = CopilotClientMode.Empty };
// after
var options = new CopilotClientOptions { Mode = CopilotClientMode.Empty, BaseDirectory = Path.Combine(appData, "sessions", sessionId) }; Defensive patterns
Strategy: validation
Validate before calling
if (options.Mode == CopilotClientMode.Empty && options.BaseDirectory is null && options.SessionFs is null && options.Connection is not UriRuntimeConnection) throw new InvalidOperationException("Empty mode requires BaseDirectory or SessionFs"); Try / catch
try { client = new CopilotClient(options); } catch (ArgumentException ex) when (ex.Message.Contains("CopilotClientMode.Empty")) { options.BaseDirectory ??= defaultSessionDir; client = new CopilotClient(options); } Prevention
- Set BaseDirectory/SessionFs whenever choosing Empty mode
- Build options through a factory that enforces Empty-mode invariants
- Add a startup unit test for each CopilotClientMode variant
When it happens
Trigger: new CopilotClient(options) where options.Mode == CopilotClientMode.Empty, BaseDirectory is null, SessionFs is null, and Connection is not a UriRuntimeConnection.
Common situations: Switching modes to Empty for isolation but forgetting to set a storage location; refactoring options builders where BaseDirectory was dropped; assuming Empty mode defaults to a temp directory (it deliberately does not).
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
- CopilotClient was created with Mode = EMPTY but neither…
- Unsupported RuntimeConnection type
- CopilotClientOptions.Environment is not supported with…
- CopilotClientOptions.Telemetry is not supported with…
- CopilotClientOptions.WorkingDirectory is not supported with…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/aa3f21ed177c096b.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Client.cs:209
_onListModels = _options.OnListModels;
_clientGlobalApis = BuildClientGlobalApis();
// Empty mode: validate at construction time that the app supplied a
// per-session persistence location. The runtime is mode-agnostic, so
// without this check it would silently fall back to ~/.copilot, which
// defeats the point of empty mode for multi-tenant scenarios.
if (_options.Mode == CopilotClientMode.Empty)
{
var hasPersistence =
!string.IsNullOrEmpty(_options.BaseDirectory) ||
_options.SessionFs is not null ||
// External runtimes manage their own persistence layer; the SDK
// can't enforce it from here.
_connection is UriRuntimeConnection;
if (!hasPersistence)
{
throw new ArgumentException(
"CopilotClient was created with Mode = CopilotClientMode.Empty but neither " +
"BaseDirectory nor SessionFs was set. Empty mode requires an explicit " +
"per-session persistence location; pick one.",
nameof(options));
}
}
}
/// <summary>
/// Validates environment-variable options against the resolved transport.
/// Per-client environment is only representable for child-process transports
/// (each client owns its own OS process). The in-process (FFI) transport
/// loads the native runtime into the shared host process, whose single
/// environment block cannot carry per-client values, so environment and
/// telemetry options that lower to environment variables are rejected there.
/// </summary>
private static void ValidateEnvironmentOptions(CopilotClientOptions options, RuntimeConnection connection)
{View on GitHub (pinned to cd8cf15dc3)