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

  1. Set options.BaseDirectory to a directory for per-session persistence
  2. Set options.SessionFs to a session filesystem implementation
  3. 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

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


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)