widget_chat is live on pub.dev — drop-in AI chat for Flutter, FlutterFlow, React & Web. Start free →

← Back to Blog
FlutterFlow Streaming API: Fix AI Chat Stuck on One Chunk

FlutterFlow Streaming API: Fix AI Chat Stuck on One Chunk

flutterflowssestreamingai chatbotonmessageflutter

FlutterFlow Streaming API: Fix AI Chat Stuck on One Chunk

You wired an AI chatbot into your FlutterFlow app, hit send, and the reply either lands all at once, prints a single token and stops, or renders nothing. The community is full of half-working Dio custom actions trying to fix this — but since FlutterFlow shipped its native Streaming API support, you don't need custom code at all. You need a real SSE endpoint, one toggle, and a correctly wired OnMessage action.

This guide walks the supported no-custom-code path end to end, using WidgetChat's streaming chat endpoint (POST https://api.widgetchat.app/v1/chat/stream, which returns token-by-token data: events over Server-Sent Events) as the backend. The same steps work for any SSE endpoint, including OpenAI's Chat Completions API.

Why FlutterFlow API streaming is "not working" — the four real causes

Almost every "flutterflow streaming api not working" thread comes down to one of these:

  1. Process Streaming Response is off. FlutterFlow buffers the entire body and delivers it once — you get the whole reply in one shot, no streaming.
  2. The endpoint isn't actually streaming. A proxy (nginx with buffering on, some serverless hosts) collects the SSE stream and flushes it as one blob. FlutterFlow can only render what arrives.
  3. OnMessage parses the payload wrong. A JSON path that doesn't match your endpoint's event shape returns null on every event — so nothing renders. A page state update that sets instead of appends leaves you with a single token.
  4. Multiple events per packet. One network packet often carries several data: lines. This is what breaks most hand-rolled Dio custom actions that split on the first newline and discard the rest.

Let's fix all four.

Step 0: Prove your endpoint streams (before blaming FlutterFlow)

Test outside FlutterFlow first with curl -N (the -N disables curl's own buffering). Copy the exact headers and request body from your provider — for WidgetChat, from your project dashboard:

curl -N -X POST "https://api.widgetchat.app/v1/chat/stream" \
  -H "Content-Type: application/json" \
  # add the auth header and JSON body exactly as shown
  # in your WidgetChat dashboard's API snippet

A healthy SSE stream prints data: lines one by one, with visible pauses:

data: <first token event>

data: <next token event>

data: <next token event>

If everything appears in a single burst at the end, the problem is server-side or proxy buffering — no FlutterFlow setting will fix that. While you're here, note the exact JSON shape inside each data: payload. You'll need it for the JSON path in Step 2. Never guess this shape from a blog post — read it off your own curl output.

Step 1: Create the API call and flip one toggle

In FlutterFlow, add an API call:

  1. API Calls → create a POST call to your streaming endpoint (e.g. https://api.widgetchat.app/v1/chat/stream).
  2. Add the headers and JSON body your provider requires — the same ones that worked in your curl test.
  3. Open Advanced Settings and enable Process Streaming Response.

That toggle is the #1 cause of "I get the whole reply at once." Without it, FlutterFlow treats the call as a normal REST request. (Note one documented limitation: multipart bodies don't work with Process Streaming Response enabled.)

Step 2: Wire the OnMessage action

With streaming enabled, the API call action exposes three response actions: OnMessage (fires for each incoming event), OnError, and OnClose.

Inside OnMessage, access the incoming data via Set Variable → Action Parameters → OnMessageInput. FlutterFlow gives you several extraction options:

  • Server Sent Event Stream Data JSON — parses the event's data: field as JSON, then lets you apply a JSON path.
  • Server Sent Event Data Text — the raw text of the data: field.
  • Server Sent Event Name / Server Sent Event ID — the event's name and sequence number.

If your endpoint's data: payload is JSON (most AI chat streams are), use Server Sent Event Stream Data JSON with a JSON path that mirrors the structure you saw in Step 0. For example, FlutterFlow's own docs use this path for OpenAI's Chat Completions stream:

$['choices'][0]['delta']['content']

For WidgetChat or any other backend, substitute the path that matches your curl output. A mismatched path silently yields null — the most common cause of a chat that renders nothing while the network tab shows data flowing.

Step 3: Accumulate tokens in a page state string

Streaming means each OnMessage delivers a fragment. You need to append, not replace:

  1. Create a page state variable, e.g. assistantReply (String, default "").
  2. In OnMessage, add Update Page StateassistantReply → set it to the current value combined with the token you extracted in Step 2.
  3. Bind a Text widget to assistantReply. It re-renders on every event — that's your token-by-token typing effect.

If you see exactly one token and then nothing, this step is your bug: you're setting the state to the latest token instead of appending it.

Null-safety gotcha: streams often include non-JSON events (a [DONE] sentinel, keep-alive comments). On those, Server Sent Event Stream Data JSON returns null, and combining null into your string can break the chain. FlutterFlow's docs recommend guarding with an inline expression:

responseData ?? ''

Placement gotcha: community reports show that updating page state from OnMessage inside an Action Block can generate code with an incorrect _model prefix or fail to rebuild the page incrementally. Keep the OnMessage logic directly on the page's action flow, not wrapped in a reusable action block.

The multi-events-per-packet gotcha

SSE makes no promise that one network packet equals one event. Under load, a single packet routinely carries several data: lines — and a custom Dio action that decodes the whole chunk as one JSON object either crashes or keeps only the first token. That's the classic "stream randomly loses words" bug in community Dio snippets.

FlutterFlow's built-in parser handles the event framing for you: OnMessage fires per event, so with the Stream Data JSON option each JSON path lookup applies to one event at a time. One caveat from the docs: if you use Server Sent Event Data Text instead, multiple entries arriving together are concatenated with newlines — so prefer the JSON option for token extraction, and treat the text option as a debugging view.

Finish the flow: OnClose and OnError

  • OnClose: the stream ended. Append the completed assistantReply to your chat message list, clear the state string for the next turn, and re-enable the send button.
  • OnError: show a snackbar and offer a retry. Don't leave the user staring at a half-rendered sentence.

Quick troubleshooting map

  • Whole reply at once → Process Streaming Response is off, or a proxy is buffering (retest with curl -N).
  • Single token, then stops → page state is being set, not appended.
  • Nothing renders → JSON path mismatch (bind Server Sent Event Data Text to a debug Text widget to see raw events), or missing ?? '' guard.
  • Works in test mode, fails on web → browser-specific SSE behavior; see our fix for SSE on Flutter Web.
  • You're in plain Flutter, not FlutterFlow → you'll want a real streaming HTTP client; see our guide to streaming with Dio's ResponseType.stream.

Where WidgetChat fits

WidgetChat is an embeddable AI support chatbot for Flutter and FlutterFlow apps that answers users from your own content. Its chat API streams replies token-by-token over SSE at POST https://api.widgetchat.app/v1/chat/stream — exactly the kind of endpoint FlutterFlow's Streaming API expects — and integrates through a plain HTTP call, no proprietary SDK required. There's a free tier, so you can have a streaming support bot rendering token-by-token in your FlutterFlow app this afternoon.

Try WidgetChat free →

FlutterFlow's official Streaming API documentation, including the OnMessage action and SSE data extraction options

WidgetChat — embeddable AI support chatbot for Flutter and FlutterFlow with SSE streaming responses

Author

About the author

Widget Chat is a team of developers and designers passionate about creating the best AI chatbot experience for Flutter, web, and mobile apps.

Comments

Comments are coming soon. We'd love to hear your thoughts!