github/copilot-sdk · error · ArgumentException
GitHubToken and GitHubTokenProvider cannot be used together.
Error message
GitHubToken and GitHubTokenProvider cannot be used together.
What it means
Thrown as ArgumentException by config validation when a session configuration supplies both GitHubToken (a static token) and GitHubTokenProvider (a delegate/provider callback). These two ways of supplying GitHub credentials are mutually exclusive by design, so the library refuses the configuration up front rather than guessing which to use.
Solutions
- Remove GitHubToken and keep only GitHubTokenProvider, or vice versa
- If merging config objects, decide precedence explicitly and null out the unused property
- Centralize GitHub credential configuration in one place to avoid both being set
Example fix
// before
var config = new SessionConfig { GitHubToken = token, GitHubTokenProvider = myProvider };
// after
var config = new SessionConfig { GitHubTokenProvider = myProvider }; // or GitHubToken = token, not both Defensive patterns
Strategy: validation
Validate before calling
if (config.GitHubToken is not null && config.GitHubTokenProvider is not null)
throw new ArgumentException("Set only one of GitHubToken or GitHubTokenProvider"); Type guard
bool HasExactlyOneGitHubCredential(SessionConfig c) => (c.GitHubToken is null) != (c.GitHubTokenProvider is null);
Try / catch
try { await client.CreateSessionAsync(config); }
catch (ArgumentException ex) when (ex.Message.Contains("cannot be used together"))
{ logger.LogError(ex, "conflicting GitHub credential config"); throw; } Prevention
- Choose one credential mechanism per app (token OR provider)
- Null out the other property when building merged configs
- Validate session config in a shared factory
- Document the exclusivity in your config schema
When it happens
Trigger: Creating a session (CreateSessionAsync/StartSessionAsync) with a SessionConfig where both config.GitHubToken is set to a string AND config.GitHubTokenProvider is set to a delegate.
Common situations: Merging config from two sources (e.g. a default template with a token plus app code adding a provider); switching from token-based to provider-based auth while leaving the old token property set; copy-pasted sample code combining both options.
Related errors
- No bearer-token provider registered for provider
- Invalid entry '*': there is no bare wildcard. Use one or…
- Invalid value ' '. Expected 'inprocess', 'stdio', or unset.
- Set environment variables via either the client-level env…
- GitHubToken and UseLoggedInUser cannot be used with CliUrl…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/6be564d960f98646.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Client.cs:2062
/// always registered because providers are configured per session.
/// </summary>
private ClientGlobalApiHandlers? BuildClientGlobalApis()
{
var handler = _options.RequestHandler;
var onGitHubTelemetry = _options.OnGitHubTelemetry;
return new ClientGlobalApiHandlers
{
LlmInference = handler is null ? null : new LlmInferenceAdapter(handler, () => _serverRpc),
GitHubTelemetry = onGitHubTelemetry is null ? null : new GitHubTelemetryAdapter(onGitHubTelemetry, _logger),
GitHubToken = new GitHubTokenAdapter(this),
};
}
private static void ValidateGitHubTokenConfig(SessionConfigBase config)
{
if (config.GitHubToken is not null && config.GitHubTokenProvider is not null)
{
throw new ArgumentException(
$"{nameof(SessionConfigBase.GitHubToken)} and {nameof(SessionConfigBase.GitHubTokenProvider)} cannot be used together.",
nameof(config));
}
}
private string? RegisterGitHubTokenProvider(
Func<GitHubTokenProviderArgs, Task<GitHubTokenProviderResult>>? provider)
{
if (provider is null)
{
return null;
}
var registrationId = Guid.NewGuid().ToString();
if (!_gitHubTokenProviders.TryAdd(registrationId, provider))
{
throw new InvalidOperationException("Failed to register GitHub token provider.");
}View on GitHub (pinned to cd8cf15dc3)