github/copilot-sdk · error · InvalidOperationException
session.create returned sessionId
Error message
session.create returned sessionId {response.SessionId} but the caller requested {localSessionId}. What it means
This InvalidOperationException is thrown by CopilotClient when the CLI's session.create RPC response returns a sessionId that does not exactly match the sessionId the caller explicitly requested for the new session. The library treats a mismatched session ID as a protocol violation, since the caller supplied localSessionId and the server must honor it. It guards callers from silently using a session under the wrong ID.
Solutions
- Remove the explicit localSessionId argument and let the CLI generate the session ID, then use response.SessionId
- Upgrade (or align) the Copilot CLI/server version so session.create honors caller-requested session IDs
- Compare versions: if you pinned a session ID for resume semantics, use the session resume/reconnect API instead of session.create
- Check for multiple connections/clients sharing the same RPC channel that could interleave responses
Example fix
// before
var session = await client.CreateSessionAsync(new SessionConfig { SessionId = myId });
// after
var session = await client.CreateSessionAsync(new SessionConfig()); // let CLI assign; use session.Id afterwards Defensive patterns
Strategy: validation
Validate before calling
if (config.SessionId is not null && string.IsNullOrWhiteSpace(config.SessionId)) throw new ArgumentException("SessionId must be null or a non-empty exact id"); Type guard
static bool IsValidRequestedSessionId(SessionConfig c) => c.SessionId is null || c.SessionId.Length > 0;
Try / catch
try { await client.CreateSessionAsync(config); }
catch (InvalidOperationException ex) when (ex.Message.Contains("session.create returned sessionId"))
{ logger.LogError(ex, "CLI ignored requested session id; falling back to server id"); /* recreate without localSessionId */ } Prevention
- Omit localSessionId unless you truly need a specific ID
- Keep CLI and SDK versions aligned
- Use session resume APIs instead of forcing IDs via session.create
- Log response.SessionId on creation to detect mismatches early
When it happens
Trigger: Calling session creation (e.g. CreateSessionAsync / StartSessionAsync) with a non-null localSessionId while the Copilot CLI server responds with a different SessionId; typically a server/CLI version that does not honor client-supplied session IDs, or a bug/misconfiguration in the connection.
Common situations: Running an older or newer Copilot CLI whose session.create implementation ignores or regenerates caller-supplied session IDs; two clients racing to create sessions with the same ID; a misrouted/proxied RPC connection replying with another session's response.
Related errors
- session.create response did not include a sessionId
- session.create response did not include a sessionId.
- Failed to delete session
- {response.Error ?? "Failed to set foreground session"}
- Unknown session
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/8af84d4daf655c1a.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Client.cs:1347
"CopilotClient.CreateSessionAsync");
}
};
var response = await InvokeRpcAsync<CreateSessionResponse>(
connection.Rpc, "session.create", [request], null, cancellationToken, onResponseInline);
LoggingHelpers.LogTiming(_logger, LogLevel.Debug, null,
"CopilotClient.CreateSessionAsync session creation request completed successfully. Elapsed={Elapsed}, SessionId={SessionId}",
rpcTimestamp,
response.SessionId);
if (session is null)
{
throw new InvalidOperationException("session.create response did not include a sessionId.");
}
if (localSessionId != null && !string.Equals(localSessionId, response.SessionId, StringComparison.Ordinal))
{
throw new InvalidOperationException(
$"session.create returned sessionId {response.SessionId} but the caller requested {localSessionId}.");
}
if (config.OnMcpAuthRequest is not null)
{
await session.Rpc.EventLog.RegisterInterestAsync("mcp.oauth_required", cancellationToken);
}
session.WorkspacePath = response.WorkspacePath;
session.SetCapabilities(response.Capabilities);
session.SetOpenCanvases(response.OpenCanvases);
await UpdateSessionOptionsForModeAsync(session, config, cancellationToken).ConfigureAwait(false);
if (registrationId is not null)
{
session.SetGitHubTokenProviderRegistration(registrationId);
registrationTransferred = true;
}View on GitHub (pinned to cd8cf15dc3)