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

  1. Set only one: either AutoTier = "<tier>" or ResetAutoTier = true, never both.
  2. If options come from merged config, null out ResetAutoTier whenever AutoTier is provided (or vice versa).
  3. 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

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


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)