github/copilot-sdk · error · ArgumentException

Set environment variables via either…

Error message

Set environment variables via either CopilotClientOptions.Environment or ChildProcessRuntimeConnection.Environment, not both. Prefer ChildProcessRuntimeConnection.Environment for child-process transports.

What it means

CopilotClient throws this ArgumentException when environment variables are specified in both CopilotClientOptions.Environment and ChildProcessRuntimeConnection.Environment. The two sources would overlap ambiguously, so the constructor rejects the combination and directs you to the connection-level setting for child-process transports.

Solutions

  1. Remove Environment from CopilotClientOptions and keep only ChildProcessRuntimeConnection.Environment.
  2. If you truly intend options-level environment, set ChildProcessRuntimeConnection.Environment to null.
  3. Centralize environment configuration in one place (prefer the connection object for child-process transports).

Example fix

// before
var options = new CopilotClientOptions { Environment = envVars };
var connection = RuntimeConnection.ForStdio(env: envVars);
var client = new CopilotClient(options, connection);
// after
var options = new CopilotClientOptions();
var connection = RuntimeConnection.ForStdio(env: envVars);
var client = new CopilotClient(options, connection);
Defensive patterns

Strategy: validation

Validate before calling

if (connection is ChildProcessRuntimeConnection { Environment: not null } && options.Environment is not null)
    throw new InvalidOperationException("Specify env vars in only one place; prefer ChildProcessRuntimeConnection.Environment.");

Type guard

static bool HasConflictingEnv(CopilotClientOptions o, ChildProcessRuntimeConnection c) => c.Environment is not null && o.Environment is not null;

Try / catch

try { client = new CopilotClient(options, connection); }
catch (ArgumentException ex) when (ex.Message.Contains("not both")) { options.Environment = null; client = new CopilotClient(options, connection); }

Prevention

When it happens

Trigger: new CopilotClient(options, connection) where connection is a ChildProcessRuntimeConnection with a non-null Environment and options.Environment is also non-null. Checked by ValidateEnvironmentOptions at construction.

Common situations: Moving environment config from the options object to the connection (or vice versa) during a refactor and leaving both populated; shared options objects used across connections that set their own Environment.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/b73c07076a66a52b. Report an issue: GitHub.

Appendix: source

Thrown at dotnet/src/Client.cs:267

            }

            if (options.WorkingDirectory is not null)
            {
                throw new ArgumentException(
                    $"{nameof(CopilotClientOptions)}.{nameof(CopilotClientOptions.WorkingDirectory)} is not supported with " +
                    $"{nameof(RuntimeConnection)}.{nameof(RuntimeConnection.ForInProcess)}(): the in-process transport hosts " +
                    "the native runtime in the shared host process and spawns the worker without a working-directory " +
                    "parameter, so a per-client working directory cannot be honored in-process. Use a child-process " +
                    "transport, or set the process working directory before creating the client.",
                    nameof(options));
            }

            return;
        }

        if (connection is ChildProcessRuntimeConnection { Environment: not null } && options.Environment is not null)
        {
            throw new ArgumentException(
                $"Set environment variables via either {nameof(CopilotClientOptions)}.{nameof(CopilotClientOptions.Environment)} " +
                $"or {nameof(ChildProcessRuntimeConnection)}.{nameof(ChildProcessRuntimeConnection.Environment)}, not both. " +
                $"Prefer {nameof(ChildProcessRuntimeConnection)}.{nameof(ChildProcessRuntimeConnection.Environment)} for " +
                "child-process transports.",
                nameof(options));
        }
    }

    /// <summary>
    /// Environment variable that overrides the transport used when the caller does not
    /// specify <see cref="CopilotClientOptions.Connection"/>. Accepts <c>"inprocess"</c>
    /// or <c>"stdio"</c> (case-insensitive); unset preserves the default stdio transport.
    /// Any other value is an error. Ignored when a <see cref="RuntimeConnection"/> is set
    /// explicitly.
    /// </summary>
    internal const string DefaultConnectionEnvVar = "COPILOT_SDK_DEFAULT_CONNECTION";

    /// <summary>

View on GitHub (pinned to cd8cf15dc3)