Slack: streamed message expires during long gaps between chunks (message_not_in_streaming_state), losing the rest of the stream
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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