{"record":{"id":"a579da59f5bca74e","repo":"mastra-ai/mastra","slug":"cannot-start-an-overlapping-websocket-responses-co","errorCode":null,"errorMessage":"Cannot start an overlapping WebSocket Responses continuation. Wait for the active stream to finish before sending previous_response_id.","messagePattern":"Cannot start an overlapping WebSocket Responses continuation\\. Wait for the active stream to finish before sending previous_response_id\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/llm/model/openai-websocket-fetch.ts","lineNumber":181,"sourceCode":"    }\n\n    let body: Record<string, unknown>;\n    try {\n      body = JSON.parse(typeof init.body === 'string' ? init.body : '');\n    } catch {\n      return globalThis.fetch(input, init);\n    }\n\n    if (!body.stream) {\n      return globalThis.fetch(input, init);\n    }\n\n    // Prevent concurrent streams from sharing one WebSocket transport instance.\n    // Only fall back to HTTP when the request does not depend on the socket's\n    // connection-local previous_response_id cache.\n    if (busy) {\n      if (body.previous_response_id) {\n        throw new Error(\n          'Cannot start an overlapping WebSocket Responses continuation. Wait for the active stream to finish before sending previous_response_id.',\n        );\n      }\n      return globalThis.fetch(input, init);\n    }\n\n    const headers = normalizeHeaders(init.headers);\n    const authorization =\n      headers['authorization'] ?? (options?.apiKeyAsBearer && headers['api-key'] ? `Bearer ${headers['api-key']}` : '');\n\n    // Acquire the busy lock before awaiting to prevent races\n    busy = true;\n    let connection: WebSocket;\n    try {\n      connection = await getConnection(authorization, headers, init?.signal);\n    } catch (err) {\n      busy = false;\n      throw err;","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/llm/model/openai-websocket-fetch.ts#L163-L199","documentation":"The OpenAI WebSocket Responses transport maintains a connection-local previous_response_id cache and supports only one active stream at a time. If a new request arrives while a stream is busy AND it carries a previous_response_id (a continuation depending on socket-local state), the library throws this Error instead of silently corrupting the conversation. Requests without previous_response_id are safely fallen back to HTTP fetch.","triggerScenarios":"Calling websocketFetch for a Responses continuation (body.previous_response_id set) while another stream is still active on the same WebSocket transport instance.","commonSituations":"Sending a follow-up message before the previous streamed response finished; concurrent agent turns sharing one client; fire-and-forget stream calls not awaited before issuing the next turn.","solutions":["Await the active stream's completion before sending a request with previous_response_id","Serialize requests through a queue/mutex per WebSocket transport instance","Use separate transport instances for concurrent conversations","Drop previous_response_id if the continuation doesn't require socket-local state (it will fall back to HTTP)"],"exampleFix":"// before\nstreamOne.start(); // not awaited\nconn.websocketFetch({ previous_response_id: 'resp_1', ... }); // throws\n// after\nawait streamOne.finished;\nawait conn.websocketFetch({ previous_response_id: 'resp_1', ... });","handlingStrategy":"fallback","validationCode":"// Guard before sending a continuation\nif (conn.isBusy && body.previous_response_id) {\n  throw new Error('Active stream in progress; defer the continuation');\n}","typeGuard":null,"tryCatchPattern":"let res;\ntry {\n  res = await conn.websocketFetch({ ...body, previous_response_id: lastId });\n} catch (e) {\n  if (e.message.includes('overlapping WebSocket Responses continuation')) {\n    await activeStream.finished; // wait, then retry the continuation\n    res = await conn.websocketFetch({ ...body, previous_response_id: lastId });\n  } else {\n    throw e;\n  }\n}","preventionTips":["Always await stream completion before sending follow-up turns with previous_response_id","Wrap each WebSocket transport in a request queue so calls are serialized","Give concurrent conversations their own transport instances","Track stream state (busy/idle) in your agent orchestration layer"],"tags":["websocket","openai","concurrency","streaming"],"backgroundTag":"concurrent-request-conflict","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}