github/copilot-sdk · error · ObjectDisposedException
Exception of type 'System.ObjectDisposedException' was…
Error message
Exception of type 'System.ObjectDisposedException' was thrown. (ObjectDisposedException(nameof(CopilotClient)))
What it means
The CopilotClient.Rpc property getter throws ObjectDisposedException(nameof(CopilotClient)) when the client has already been disposed. It guards access to the internal server RPC channel so callers never touch a dead connection.
Solutions
- Ensure all Rpc usage completes before disposing the client
- Check the client's disposed state before accessing Rpc
- Recreate a new CopilotClient (and StartAsync) if disposal was unintentional
Example fix
// before
var rpc = client.Rpc;
// after
if (client is { }) { var rpc = client.Rpc; } // only while client is alive/not disposed Defensive patterns
Strategy: try-catch
Validate before calling
// no public disposed flag; track it at the call site bool clientAlive = !disposedFlag;
Try / catch
try { var rpc = client.Rpc; } catch (ObjectDisposedException) { client = new CopilotClient(options); await client.StartAsync(); var rpc = client.Rpc; } Prevention
- Scope the client so all Rpc consumers finish before disposal
- Dispose the client only after in-flight work completes
- Track disposal in a wrapper owning the client lifetime
When it happens
Trigger: Reading the Rpc property after calling DisposeAsync/Dispose on the CopilotClient.
Common situations: Background tasks or event handlers outliving the client's lifetime; accessing Rpc from a finalizer or after a cancellation-triggered shutdown; holding a stale client reference across a reconnect cycle.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Client is not started. Call StartAsync first.
- Runtime process not started
- Unknown session
- CLI process not started
- CLI child process was unexpectedly started in parent…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/e637353fda1f24d3.
Report an issue: GitHub.
Appendix: source
Thrown at dotnet/src/Client.cs:111
/// <summary>
/// Client-global RPC handlers (e.g. the LLM inference provider adapter),
/// built once at construction and registered on every connection.
/// </summary>
private readonly ClientGlobalApiHandlers? _clientGlobalApis;
private sealed record LifecycleSubscription(Type EventType, Action<SessionLifecycleEvent> Handler);
/// <summary>
/// Gets the typed RPC client for server-scoped methods (no session required).
/// </summary>
/// <remarks>
/// The client must be started before accessing this property. Call <see cref="StartAsync"/> before use.
/// </remarks>
/// <exception cref="ObjectDisposedException">Thrown if the client has been disposed.</exception>
/// <exception cref="InvalidOperationException">Thrown if the client is not started.</exception>
public ServerRpc Rpc => _disposed
? throw new ObjectDisposedException(nameof(CopilotClient))
: _serverRpc ?? throw new InvalidOperationException("Client is not started. Call StartAsync first.");
/// <summary>
/// Gets the actual TCP port the runtime is listening on, if using TCP transport.
/// </summary>
public int? RuntimePort => _actualPort;
/// <summary>
/// Creates a new instance of <see cref="CopilotClient"/>.
/// </summary>
/// <param name="options">Options for creating the client. If null, default options are used.</param>
/// <example>
/// <code>
/// // Default options - spawns the bundled runtime using stdio
/// var client = new CopilotClient();
///
/// // Connect to an existing runtime
/// var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri("localhost:3000") });View on GitHub (pinned to cd8cf15dc3)