{"record":{"id":"54e62c389daee9ca","repo":"mastra-ai/mastra","slug":"no-response-body","errorCode":null,"errorMessage":"No response body","messagePattern":"No response body","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client-sdks/client-js/src/resources/agent.ts","lineNumber":642,"sourceCode":"      unsubscribe: () => void;\n    }\n  > {\n    const { resourceId, threadId } = params;\n    const requestSubscription = () =>\n      this.request(`/agents/${this.agentId}/threads/subscribe`, {\n        method: 'POST',\n        body: { resourceId, threadId },\n        stream: true,\n      }) as Promise<Response>;\n\n    const streamResponse = (await requestSubscription()) as Response & {\n      processDataStream: (options: ProcessAgentThreadStreamOptions) => Promise<void>;\n      abort: () => Promise<boolean>;\n      unsubscribe: () => void;\n    };\n\n    if (!streamResponse.body) {\n      throw new Error('No response body');\n    }\n\n    const agent = this;\n    streamResponse.abort = async () => (await agent.abortThread({ resourceId, threadId })).aborted;\n\n    let unsubscribed = false;\n    let processAbortController: AbortController | undefined;\n    let processStarted = false;\n\n    streamResponse.unsubscribe = () => {\n      if (unsubscribed) return;\n      unsubscribed = true;\n      processAbortController?.abort();\n      if (!processStarted) {\n        void streamResponse.body?.cancel().catch(() => {});\n      }\n    };\n","sourceCodeStart":624,"sourceCodeEnd":660,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/client-sdks/client-js/src/resources/agent.ts#L624-L660","documentation":"In agent.ts subscribeToThread(), after subscribing to a thread's stream the client checks streamResponse.body and throws 'No response body' if it is missing, since the returned subscription object needs a ReadableStream to process agent thread data chunks. This is an early guard before wiring up processDataStream and abort handlers.","triggerScenarios":"The thread subscription request returns ok but body is null: mocks without a body, buffering infrastructure on the subscribe route, or a fetch implementation without streaming bodies.","commonSituations":"Frontend tests mocking the thread subscribe endpoint with only { ok: true }; gateways/CDNs buffering the SSE stream to empty; older polyfilled fetch in legacy browsers or constrained runtimes.","solutions":["Ensure the server's thread subscribe endpoint streams data (test with curl -N).","Fix test mocks to supply a ReadableStream body.","Upgrade to an environment with native streaming fetch (modern browsers, Node 18+).","Check proxies/CDNs (e.g. buffering middleware) aren't stripping the stream.","Try/catch around subscribeToThread and fall back to polling thread messages."],"exampleFix":"// before\nconst sub = await agent.subscribeToThread({ resourceId, threadId });\n// after\ntry {\n  const sub = await agent.subscribeToThread({ resourceId, threadId });\n} catch (e) {\n  if ((e as Error).message === 'No response body') {\n    console.error('Subscribe returned no body — falling back to polling');\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"const res = await fetch(subscribeUrl);\nif (res.ok && !res.body) throw new Error('Thread subscribe returns no body in this environment');","typeGuard":"function hasBody(res: Response): res is Response & { body: ReadableStream<Uint8Array> } { return res.body != null; }","tryCatchPattern":"try {\n  const sub = await agent.subscribeToThread({ resourceId, threadId });\n} catch (err) {\n  if ((err as Error).message === 'No response body') {\n    console.error('Subscribe got no stream body — check mocks/proxies, consider polling thread messages');\n  }\n  throw err;\n}","preventionTips":["Mock subscribe endpoints with ReadableStream bodies","Verify subscribe endpoint streams in the target environment","Avoid CDN/proxy buffering on SSE routes","Provide a polling fallback for thread messages"],"tags":["streaming","null","memory","subscription"],"backgroundTag":"null-response-body","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}