{"record":{"id":"b73c07076a66a52b","repo":"github/copilot-sdk","slug":"set-environment-variables-via-either-copilotclient","errorCode":null,"errorMessage":"Set environment variables via either CopilotClientOptions.Environment or ChildProcessRuntimeConnection.Environment, not both. Prefer ChildProcessRuntimeConnection.Environment for child-process transports.","messagePattern":"Set environment variables via either CopilotClientOptions\\.Environment or ChildProcessRuntimeConnection\\.Environment, not both\\. Prefer ChildProcessRuntimeConnection\\.Environment for child-process transports\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Client.cs","lineNumber":267,"sourceCode":"            }\n\n            if (options.WorkingDirectory is not null)\n            {\n                throw new ArgumentException(\n                    $\"{nameof(CopilotClientOptions)}.{nameof(CopilotClientOptions.WorkingDirectory)} is not supported with \" +\n                    $\"{nameof(RuntimeConnection)}.{nameof(RuntimeConnection.ForInProcess)}(): the in-process transport hosts \" +\n                    \"the native runtime in the shared host process and spawns the worker without a working-directory \" +\n                    \"parameter, so a per-client working directory cannot be honored in-process. Use a child-process \" +\n                    \"transport, or set the process working directory before creating the client.\",\n                    nameof(options));\n            }\n\n            return;\n        }\n\n        if (connection is ChildProcessRuntimeConnection { Environment: not null } && options.Environment is not null)\n        {\n            throw new ArgumentException(\n                $\"Set environment variables via either {nameof(CopilotClientOptions)}.{nameof(CopilotClientOptions.Environment)} \" +\n                $\"or {nameof(ChildProcessRuntimeConnection)}.{nameof(ChildProcessRuntimeConnection.Environment)}, not both. \" +\n                $\"Prefer {nameof(ChildProcessRuntimeConnection)}.{nameof(ChildProcessRuntimeConnection.Environment)} for \" +\n                \"child-process transports.\",\n                nameof(options));\n        }\n    }\n\n    /// <summary>\n    /// Environment variable that overrides the transport used when the caller does not\n    /// specify <see cref=\"CopilotClientOptions.Connection\"/>. Accepts <c>\"inprocess\"</c>\n    /// or <c>\"stdio\"</c> (case-insensitive); unset preserves the default stdio transport.\n    /// Any other value is an error. Ignored when a <see cref=\"RuntimeConnection\"/> is set\n    /// explicitly.\n    /// </summary>\n    internal const string DefaultConnectionEnvVar = \"COPILOT_SDK_DEFAULT_CONNECTION\";\n\n    /// <summary>","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/dotnet/src/Client.cs#L249-L285","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove Environment from CopilotClientOptions and keep only ChildProcessRuntimeConnection.Environment.","If you truly intend options-level environment, set ChildProcessRuntimeConnection.Environment to null.","Centralize environment configuration in one place (prefer the connection object for child-process transports)."],"exampleFix":"// before\nvar options = new CopilotClientOptions { Environment = envVars };\nvar connection = RuntimeConnection.ForStdio(env: envVars);\nvar client = new CopilotClient(options, connection);\n// after\nvar options = new CopilotClientOptions();\nvar connection = RuntimeConnection.ForStdio(env: envVars);\nvar client = new CopilotClient(options, connection);","handlingStrategy":"validation","validationCode":"if (connection is ChildProcessRuntimeConnection { Environment: not null } && options.Environment is not null)\n    throw new InvalidOperationException(\"Specify env vars in only one place; prefer ChildProcessRuntimeConnection.Environment.\");","typeGuard":"static bool HasConflictingEnv(CopilotClientOptions o, ChildProcessRuntimeConnection c) => c.Environment is not null && o.Environment is not null;","tryCatchPattern":"try { client = new CopilotClient(options, connection); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"not both\")) { options.Environment = null; client = new CopilotClient(options, connection); }","preventionTips":["Pick one canonical location for env config (prefer the connection)","Build options objects without Environment when connections set their own","Add a config-loading assertion that only one source is populated"],"tags":["dotnet","configuration","environment-variables","child-process"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}