github/copilot-sdk · error · ArgumentException
SetModelOptions.AutoTier and SetModelOptions.ResetAutoTier…
Error message
SetModelOptions.AutoTier and SetModelOptions.ResetAutoTier are mutually exclusive.
What it means
SetModelAsync validates SetModelOptions before applying: AutoTier (set a specific auto-tier) and ResetAutoTier (clear auto-tier) are contradictory operations, so supplying both non-null AutoTier and ResetAutoTier=true is rejected with ArgumentException, with nameof(options) as paramName.
Solutions
- Set only one: either AutoTier = "<tier>" or ResetAutoTier = true, never both.
- If options come from merged config, null out ResetAutoTier whenever AutoTier is provided (or vice versa).
- Catch ArgumentException (paramName == "options") to report a clear validation message to the user.
Example fix
// before
await session.SetModelAsync("gpt-5", new SetModelOptions { AutoTier = "premium", ResetAutoTier = true });
// after
var opts = new SetModelOptions { AutoTier = "premium", ResetAutoTier = opts?.AutoTier is null };
await session.SetModelAsync("gpt-5", opts.AutoTier is null ? new SetModelOptions { ResetAutoTier = true } : new SetModelOptions { AutoTier = opts.AutoTier }); Defensive patterns
Strategy: validation
Validate before calling
if (options.AutoTier is not null && options.ResetAutoTier)
throw new ArgumentException("Set only one of AutoTier or ResetAutoTier", nameof(options)); Type guard
static bool OptionsConsistent(SetModelOptions o) => o.AutoTier is null || !o.ResetAutoTier;
Try / catch
try { await session.SetModelAsync(model, options); }
catch (ArgumentException ex) when (ex.ParamName == "options" && ex.Message.Contains("mutually exclusive"))
{ NotifyUser("Choose either an auto tier or a reset, not both."); } Prevention
- Never merge AutoTier and ResetAutoTier from independent config sources
- Null out ResetAutoTier when AutoTier is set after merging options
- Centralize option construction in one factory to keep invariants
When it happens
Trigger: Calling session.SetModelAsync(model, new SetModelOptions { AutoTier = "premium", ResetAutoTier = true }) — any call where both properties are set.
Common situations: Merging user-supplied settings objects where ResetAutoTier defaults true and AutoTier was also filled from config; copy-paste of option objects across code paths; UI forms that submit both fields.
Related errors
- GitHubToken and GitHubTokenProvider cannot be used together.
- The value cannot be an empty string or composed entirely of…
- Invalid tool name: must not be null or empty.
- Invalid entry '*': there is no bare wildcard. Use one or…
- Client is not connected. Call start() first.
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/2a7191d4350e1d8e.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Session.cs:2037
},
cancellationToken);
}
/// <summary>
/// Changes the model for this session.
/// The new model takes effect for the next message. Conversation history is preserved.
/// </summary>
/// <param name="model">Model ID to switch to (e.g., "gpt-5.4").</param>
/// <param name="options">Settings for the new model.</param>
/// <param name="cancellationToken">Optional cancellation token.</param>
public async Task SetModelAsync(string model, SetModelOptions options, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(model);
ThrowIfDisposed();
if (options.AutoTier is not null && options.ResetAutoTier)
{
throw new ArgumentException(
$"{nameof(SetModelOptions.AutoTier)} and {nameof(SetModelOptions.ResetAutoTier)} are mutually exclusive.",
nameof(options));
}
if (options.ResetAutoTier)
{
var request = new ModelSwitchToRequest
{
SessionId = SessionId,
ModelId = model,
ReasoningEffort = options.ReasoningEffort,
ReasoningSummary = options.ReasoningSummary,
ModelCapabilities = options.ModelCapabilities,
ContextTier = options.ContextTier,
};
await CopilotClient.InvokeRpcAsync(
Rpc,
"session.model.switchTo",View on GitHub (pinned to cd8cf15dc3)