vercel / vercel/chat

Slack: streamed message expires during long gaps between chunks (message_not_in_streaming_state), losing the rest of the stream

Open
#607 0 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
2.4k
Forks
314
Avg merge
1d 18h
Merged PRs (30d)
63

Description

Summary

On Slack, thread.post(asyncIterable) opens one native streaming message and appends each chunk. Slack expires a message's streaming state when appends stop flowing for a while (it's designed for active token streams). With a slow producer — e.g. an agent that emits a message, runs tools for a few minutes, then emits the next one — the next append after a long gap throws message_not_in_streaming_state, the error propagates out of thread.post, and every remaining chunk is lost.

Repro

await thread.post((async function* () {
  yield "part one"
  await new Promise((r) => setTimeout(r, 5 * 60_000))
  yield "part two" // throws message_not_in_streaming_state
})())
Error: An API error occurred: message_not_in_streaming_state
    at ChatStreamer.flushBuffer (@slack/web-api/src/chat-stream.ts)
    at ChatStreamer.append
    at flushMarkdownDelta (@chat-adapter/slack)
    at _SlackAdapter.stream
    at _ThreadImpl.handleStream

Expected

The docs say any AsyncIterable<string> works, with no documented cadence constraint — and the SDK already has post+edit / buffered fallbacks for other platforms. When the stream state expires, the adapter could finalize what was streamed and deliver the remaining chunks via the post+edit fallback (or a fresh streamed message), instead of throwing away the tail.

Context

Hit this wiring a long-running agent (minutes-long tool calls between messages) to Slack via the Chat SDK.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the delayed AsyncIterable reproduction and trace the failure through @slack/web-api/src/chat-stream.ts, flushMarkdownDelta, _SlackAdapter.stream, and _ThreadImpl.handleStream. Check the existing post+edit or buffered fallbacks for other platforms. Done means a long gap does not lose remaining chunks or cause thread.post to fail with message_not_in_streaming_state.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
62/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.