github/copilot-sdk · error · InvalidOperationException

WebSocket response bridge is not attached.

Error message

WebSocket response bridge is not attached.

What it means

CopilotWebSocketHandler's constructor requires the CopilotRequestContext to carry a WebSocket response bridge used to deliver responses upstream. This InvalidOperationException is thrown at handler construction when context.WebSocketResponse is null, meaning the handler cannot send anything back.

Solutions

  1. Attach the WebSocket response bridge to the CopilotRequestContext before constructing the handler (context.WebSocketResponse = ...)
  2. Use the library's factory/context-builder methods instead of hand-constructing CopilotRequestContext
  3. Check for a version mismatch where your transport predates the WebSocketResponse property

Example fix

// before
var handler = new MyHandler(new CopilotRequestContext { WebSocket = ws });
// after
var handler = new MyHandler(new CopilotRequestContext { WebSocket = ws, WebSocketResponse = bridge });
Defensive patterns

Strategy: validation

Validate before calling

if (context.WebSocketResponse is null) throw new InvalidOperationException("Attach WebSocketResponse bridge before creating the handler");

Type guard

static bool BridgeAttached(CopilotRequestContext ctx) => ctx.WebSocketResponse is not null;

Try / catch

try { var handler = new MyHandler(context); }
catch (InvalidOperationException ex) when (ex.Message.Contains("response bridge")) { /* fix context wiring */ }

Prevention

When it happens

Trigger: Constructing a derived CopilotWebSocketHandler with a CopilotRequestContext whose WebSocketResponse bridge was never attached (e.g. context built manually or by a transport that skipped bridge wiring).

Common situations: Custom transport implementations create request contexts without calling the bridge-attachment step; testing code constructs contexts by hand; an upgrade changed how the bridge is attached to the context.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/f383c6876c96a38a. Report an issue: GitHub.

Appendix: source

Thrown at dotnet/src/CopilotRequestHandler.cs:168

public abstract class CopilotWebSocketHandler : IAsyncDisposable
{
    private readonly TaskCompletionSource<CopilotWebSocketCloseStatus> _completion =
        new(TaskCreationOptions.RunContinuationsAsynchronously);
    private int _closed;
    private bool _suppressCloseOnDispose;

    /// <summary>Request context for this WebSocket connection.</summary>
    protected CopilotRequestContext Context { get; }

    internal Task<CopilotWebSocketCloseStatus> Completion => _completion.Task;

    /// <summary>
    /// Initializes a per-connection handler for the supplied request context.
    /// </summary>
    protected CopilotWebSocketHandler(CopilotRequestContext context)
    {
        Context = context;
        _ = context.WebSocketResponse ?? throw new InvalidOperationException("WebSocket response bridge is not attached.");
    }

    /// <summary>
    /// Send a message from the runtime to the upstream connection.
    /// </summary>
    public abstract Task SendRequestMessageAsync(CopilotWebSocketMessage message);

    /// <summary>
    /// Send a message from the upstream connection back to the runtime.
    /// Override to mutate or duplicate messages; call <c>base</c> to emit.
    /// </summary>
    public virtual Task SendResponseMessageAsync(CopilotWebSocketMessage message) =>
        Context.WebSocketResponse!.WriteAsync(message);

    /// <summary>
    /// Close the connection and finalise the runtime-facing response.
    /// </summary>
    public virtual async Task CloseAsync(CopilotWebSocketCloseStatus status)

View on GitHub (pinned to cd8cf15dc3)