Skip to content

BedrockAgentCoreApp throws FastifyError (invalid payload type) when invocation handler returns async generator with Accept: text/event-stream #66

@stewartmoreland

Description

@stewartmoreland

Describe the bug

When the invocation handler is an async generator (or a sync function that returns an async generator) and the client sends Accept: text/event-stream, the request completes with HTTP 500. The runtime calls reply.send(payload) with an object somewhere, and Fastify throws: "Attempted to send payload of invalid type 'object'. Expected a string or Buffer." (FST_ERR_REP_INVALID_PAYLOAD_TYPE).

To Reproduce

Steps to reproduce the behavior:

  1. Install package: yarn add bedrock-agentcore zod (or npm equivalent).
  2. Create a server using the code sample below and run it.
  3. Send POST /invocations with header Accept: text/event-stream and body { "prompt": "hello" }.
  4. See error (500 and FastifyError in logs).

Expected behavior

The runtime should stream SSE events from the async generator without calling reply.send() with an object. The client should receive text/event-stream chunks from reply.sse.send(...).

Code Sample

import { BedrockAgentCoreApp } from 'bedrock-agentcore/runtime';
import { z } from 'zod';

const app = new BedrockAgentCoreApp({
  invocationHandler: {
    requestSchema: z.object({ prompt: z.string() }),
    process(request, ctx) {
      async function* stream() {
        yield JSON.stringify({ type: 'meta', sessionId: ctx.sessionId });
      }
      return stream();
    },
  },
});

app.run();

Error Output

FastifyError: Attempted to send payload of invalid type 'object'. Expected a string or Buffer.
    at onSendEnd (node_modules/fastify/lib/reply.js:652:11)
    at onSendHook (node_modules/fastify/lib/reply.js:539:5)
    at Reply.send (node_modules/fastify/lib/reply.js:210:3)
    at BedrockAgentCoreApp._handleInvocation (node_modules/bedrock-agentcore/src/runtime/app.ts:403:31)
    at Object.sseHandler (node_modules/@fastify/sse/index.js:437:37)
    ...
"msg":"Promise errored, but reply.sent = true was set"

Environment (please complete the following information):

  • OS: macOS 15.7.3 (24G419)
  • Node.js version: Tested with 22.15.1 and 24.13.0 — same result on both
  • Package version: bedrock-agentcore@0.2.0
  • AWS SDK version: N/A (runtime uses Fastify 5.7.4 and @fastify/sse 0.2.0 via SDK)

Additional context

  • Yielding only strings from the generator does not fix it, so the failure is likely not from the first chunk type.
  • Using a sync process that returns the generator (so the runtime receives an AsyncGenerator, not a Promise) still reproduces the issue.
  • Stack trace points to _handleInvocation (app.ts:403), so the invalid reply.send(object) is inside the runtime.
  • Likely causes: (1) non-streaming branch taken and reply.send(result) is called with the generator object, or (2) catch block calls reply.status(500).send({ error }) after SSE has started, and the object is not serialized.

Possible Solution

  1. Streaming branch: When the handler returns an async generator and the request has SSE, never call reply.send(result); only use reply.sse.send(...).
  2. Chunk type in _handleStreamingResponse: Before reply.sse.send(chunk), coerce to string or Buffer: typeof chunk === 'string' ? chunk : Buffer.isBuffer(chunk) ? chunk : JSON.stringify(chunk).
  3. Catch block: If reply.raw?.headersSent, do not call reply.status(500).send(...); optionally send an SSE error event or only log. If sending a JSON error body, call reply.type('application/json') first so Fastify serializes the object.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions