{"record":{"id":"f383c6876c96a38a","repo":"github/copilot-sdk","slug":"websocket-response-bridge-is-not-attached-f383c6","errorCode":null,"errorMessage":"WebSocket response bridge is not attached.","messagePattern":"WebSocket response bridge is not attached\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/CopilotRequestHandler.cs","lineNumber":168,"sourceCode":"public abstract class CopilotWebSocketHandler : IAsyncDisposable\n{\n    private readonly TaskCompletionSource<CopilotWebSocketCloseStatus> _completion =\n        new(TaskCreationOptions.RunContinuationsAsynchronously);\n    private int _closed;\n    private bool _suppressCloseOnDispose;\n\n    /// <summary>Request context for this WebSocket connection.</summary>\n    protected CopilotRequestContext Context { get; }\n\n    internal Task<CopilotWebSocketCloseStatus> Completion => _completion.Task;\n\n    /// <summary>\n    /// Initializes a per-connection handler for the supplied request context.\n    /// </summary>\n    protected CopilotWebSocketHandler(CopilotRequestContext context)\n    {\n        Context = context;\n        _ = context.WebSocketResponse ?? throw new InvalidOperationException(\"WebSocket response bridge is not attached.\");\n    }\n\n    /// <summary>\n    /// Send a message from the runtime to the upstream connection.\n    /// </summary>\n    public abstract Task SendRequestMessageAsync(CopilotWebSocketMessage message);\n\n    /// <summary>\n    /// Send a message from the upstream connection back to the runtime.\n    /// Override to mutate or duplicate messages; call <c>base</c> to emit.\n    /// </summary>\n    public virtual Task SendResponseMessageAsync(CopilotWebSocketMessage message) =>\n        Context.WebSocketResponse!.WriteAsync(message);\n\n    /// <summary>\n    /// Close the connection and finalise the runtime-facing response.\n    /// </summary>\n    public virtual async Task CloseAsync(CopilotWebSocketCloseStatus status)","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/dotnet/src/CopilotRequestHandler.cs#L150-L186","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Attach the WebSocket response bridge to the CopilotRequestContext before constructing the handler (context.WebSocketResponse = ...)","Use the library's factory/context-builder methods instead of hand-constructing CopilotRequestContext","Check for a version mismatch where your transport predates the WebSocketResponse property"],"exampleFix":"// before\nvar handler = new MyHandler(new CopilotRequestContext { WebSocket = ws });\n// after\nvar handler = new MyHandler(new CopilotRequestContext { WebSocket = ws, WebSocketResponse = bridge });","handlingStrategy":"validation","validationCode":"if (context.WebSocketResponse is null) throw new InvalidOperationException(\"Attach WebSocketResponse bridge before creating the handler\");","typeGuard":"static bool BridgeAttached(CopilotRequestContext ctx) => ctx.WebSocketResponse is not null;","tryCatchPattern":"try { var handler = new MyHandler(context); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"response bridge\")) { /* fix context wiring */ }","preventionTips":["Always construct CopilotRequestContext through the library's builders","Never hand-roll request contexts in custom transports","Re-check context wiring after upgrading the library"],"tags":["websocket","initialization","dotnet"],"backgroundTag":"missing-required-config-field","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}