From 5d178ada9f3889fe878bd74a8ead4132a6cdec9f Mon Sep 17 00:00:00 2001 From: Susana Ferreira Date: Mon, 25 May 2026 17:57:02 +0100 Subject: [PATCH] docs(aibridge): document known IsStreaming race condition (#25654) Documents the known race in `EventStream.IsStreaming()` and the resulting flake in `TestStreamingInterception_AgenticLoopFailover/agentic_all_keys_fail `, accepted rather than fixed since the inner agentic loop is on track to be removed as part of the reverse proxy migration in coder/aibridge#223. Full reasoning in coder/internal#1524. --- aibridge/intercept/eventstream/eventstream.go | 9 +++++++++ aibridge/intercept/messages/streaming_internal_test.go | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/aibridge/intercept/eventstream/eventstream.go b/aibridge/intercept/eventstream/eventstream.go index fd15d6b4ef..939525012e 100644 --- a/aibridge/intercept/eventstream/eventstream.go +++ b/aibridge/intercept/eventstream/eventstream.go @@ -219,6 +219,15 @@ func (s *EventStream) Shutdown(shutdownCtx context.Context) error { // IsStreaming checks if the stream has been initiated, or // when events are buffered which - when processed - will initiate the stream. +// +// Note: there is a known race between the channel pop in Start and the +// subsequent InitiateStream call where this can briefly return false for +// a stream that's about to begin. Callers that use this to choose between +// JSON and SSE response formats can produce a malformed response under +// that race. Accepted until the MCP Gateway migration results in AI +// Gateway behaving like a reverse proxy, removing the inner agentic loop +// code. See https://github.com/coder/aibridge/issues/223 and +// https://github.com/coder/internal/issues/1524. func (s *EventStream) IsStreaming() bool { return s.initiated.Load() || len(s.eventsCh) > 0 } diff --git a/aibridge/intercept/messages/streaming_internal_test.go b/aibridge/intercept/messages/streaming_internal_test.go index 075a15264e..97f48d4cc3 100644 --- a/aibridge/intercept/messages/streaming_internal_test.go +++ b/aibridge/intercept/messages/streaming_internal_test.go @@ -434,6 +434,10 @@ func TestStreamingInterception_AgenticLoopFailover(t *testing.T) { // keys 429 during the agentic continuation. // Then: 3 requests, error injected as SSE event, both // keys temporary. + // + // Known flake: race in eventstream.IsStreaming() can + // produce a malformed response on the all-keys-exhausted + // path. See https://github.com/coder/internal/issues/1524. name: "agentic_all_keys_fail", responses: []upstreamResponse{ {statusCode: http.StatusOK, headers: sseHeaders, body: toolUseStreamBody},