mastra-ai/mastra · error

Response body is null

Error message

Response body is null

What it means

After an ok response from the agent-builder stream endpoint, the client requires a ReadableStream body to pipe through its record parser. A 2xx response with a null body cannot be streamed and triggers this throw.

Source

Thrown at client-sdks/client-js/src/resources/agent-builder.ts:210

    const searchParams = new URLSearchParams();
    searchParams.set('runId', runId);

    const requestContext = parseClientRequestContext(params.requestContext);
    const { requestContext: _, ...actionParams } = params;

    const url = `/agent-builder/${this.actionId}/stream?${searchParams.toString()}`;
    const response: Response = await this.request(url, {
      method: 'POST',
      body: { ...actionParams, requestContext },
      stream: true,
    });

    if (!response.ok) {
      throw new Error(`Failed to stream agent builder action: ${response.statusText}`);
    }

    if (!response.body) {
      throw new Error('Response body is null');
    }

    return response.body.pipeThrough(this.createRecordParserTransform());
  }

  /**
   * Observes an existing agent builder action run stream.
   * Replays cached execution from the beginning, then continues with live stream.
   * This is the recommended method for recovery after page refresh/hot reload.
   * This calls `/agent-builder/:actionId/observe`
   */
  async observeStream(params: { runId: string }): Promise<globalThis.ReadableStream<{ type: string; payload: any }>> {
    const searchParams = new URLSearchParams();
    searchParams.set('runId', params.runId);

    const url = `/agent-builder/${this.actionId}/observe?${searchParams.toString()}`;
    const response: Response = await this.request(url, {
      method: 'POST',

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Use a runtime with native streaming fetch support (Node 18+, modern browsers).
  2. Remove interceptors/polyfills that consume the response body.
  3. In tests, mock with a Response constructed from a real ReadableStream body.

Example fix

// before
mockFetch.mockResolvedValue(new Response(null, { status: 200 }));
// after
mockFetch.mockResolvedValue(new Response(someReadableStream, { status: 200 }));
Defensive patterns

Strategy: type-guard

Type guard

function hasBody(res: Response): res is Response & { body: ReadableStream<Uint8Array> } {
  return res.body !== null;
}

Try / catch

try {
  const stream = await agentBuilder.stream(action, runId);
} catch (e) {
  if (e instanceof Error && e.message === 'Response body is null') {
    // streaming unsupported in this runtime; poll the action status instead
  }
  throw e;
}

Prevention

When it happens

Trigger: agentBuilder.stream(action, runId) receives an ok response whose body was consumed or never produced — fetch polyfills, response interceptors, or empty 2xx responses from a proxy.

Common situations: Test mocks returning Response without a body; react-native/polyfilled fetch without streaming support; middleware reading response.body before the client.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/5f3fb2e4d20a2e2d. Report an issue: GitHub.