Skip to content

fix(slack): route stream-fallback delivery through chunked sender (follow-up to #70370)#71124

Merged
steipete merged 3 commits into
openclaw:mainfrom
martingarramon:fix/slack-stream-fallback-chunked
Apr 24, 2026
Merged

fix(slack): route stream-fallback delivery through chunked sender (follow-up to #70370)#71124
steipete merged 3 commits into
openclaw:mainfrom
martingarramon:fix/slack-stream-fallback-chunked

Conversation

@martingarramon

Copy link
Copy Markdown
Contributor

deliverPendingStreamFallback was calling chat.postMessage directly for err.pendingText, which bypasses the chunked reply path used everywhere else. For Slack Connect cases where the buffered tail exceeds Slack's single-message text limit, the raw post failed with msg_too_long and the unsent tail was dropped. Relatedly, non-benign streaming errors left pendingText populated on the session so the post-loop finalize re-posted the same chunk that deliverNormally had already sent.

Two changes, one concern (stream-fallback delivery hardening):

  1. deliverPendingStreamFallback routes through deliverReplies, which chunks long text and honors the configured replyToMode / identity.
  2. The non-benign streaming-error branch in deliverWithStreaming clears the session via markSlackStreamFallbackDelivered before falling back to deliverNormally. Without this, pendingText stays populated and the post-loop finalize (stopSlackStreamSlackStreamNotDeliveredError → fallback) re-posts the same chunk that deliverNormally already sent.

What this addresses

The remaining Codex P1 on extensions/slack/src/streaming.ts:247 about silently swallowing finalize errors when the SDK buffer may still be non-empty touches a different file and a different class of concern — I would rather ship that as a separate follow-up than fold it in here.

Suggested release note

Fix: Slack fallback for streamed replies no longer drops long buffered text on Slack Connect recipient errors, and no longer duplicates the buffered chunk when a streaming API call fails mid-turn.

Testing

  • pnpm check:changed green: extension-test typecheck, pnpm lint:extensions (5057 files, 211 rules, 0 warnings / 0 errors), pnpm check:import-cycles (0 runtime cycles), 75 tests passed across 6 files.
  • Targeted file dispatch.preview-fallback.test.ts: 4 pre-existing tests preserved, 2 updated to assert the new chunked routing, 2 new regressions added — oversized pendingText forwarded intact with textLimit: 4000, and non-benign-error path clears stream state so finalize skips without reposting.
  • dispatch.streaming.test.ts + streaming.test.ts: 35/35 green.

Follow-up to #70370.

@openclaw-barnacle openclaw-barnacle Bot added channel: slack Channel integration: slack size: S labels Apr 24, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 44bd320a97

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 651 to 654
if (streamSession) {
markSlackStreamFallbackDelivered(streamSession);
}
await deliverNormally({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve pending buffered text on non-benign stream errors

Do not clear the stream session before fallback delivery here: markSlackStreamFallbackDelivered(streamSession) empties pendingText before deliverNormally runs, so any earlier buffered text is lost when a non-benign append/start error happens. For example, if chunk A is buffered in the SDK and appending chunk B throws a generic network error, this branch drops A+B from pendingText and only sends payload B via deliverNormally, which can silently truncate the final reply content.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — you're right, clearing pendingText dropped anything the SDK had buffered from earlier turns. Fixed in ba81aba8: on non-benign streaming errors with non-empty pendingText, route the full buffer through deliverPendingStreamFallback with a synthetic SlackStreamNotDeliveredError and skip deliverNormally (the current payload's text is already included in pendingText per appendSlackStream's accumulation). Falls back to deliverNormally only if the chunked send itself fails. Test updated to assert the full buffered content ("first buffered\nsecond payload") gets routed through deliverReplies.

@greptile-apps

greptile-apps Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR hardens Slack stream-fallback delivery with two focused fixes: deliverPendingStreamFallback now routes through deliverReplies (honoring textLimit, replyToMode, and identity) instead of a bare chat.postMessage, eliminating msg_too_long failures for Slack Connect cases; and the non-benign error branch in deliverWithStreaming calls markSlackStreamFallbackDelivered before falling back to deliverNormally, preventing the post-loop finalize from re-posting the same buffered chunk via stopSlackStream → SlackStreamNotDeliveredError. Both changes are well-exercised by the updated and new regression tests.

Confidence Score: 5/5

Safe to merge — all changed paths have tight test coverage and no P0/P1 issues were found.

Both fixes are narrowly scoped, logically consistent with stopSlackStream's stopped/pendingText contract, and verified by four targeted regression tests (two updated, two new). No silent data loss, no duplicate delivery path, no security concern introduced.

No files require special attention.

Reviews (1): Last reviewed commit: "fix(slack): route stream-fallback delive..." | Re-trigger Greptile

@steipete
steipete force-pushed the fix/slack-stream-fallback-chunked branch from ba81aba to 1fb3d9f Compare April 24, 2026 21:45
martingarramon and others added 3 commits April 24, 2026 22:46
deliverPendingStreamFallback was calling chat.postMessage directly for
err.pendingText, which bypasses the chunked reply path used everywhere
else. For Slack Connect cases where appendSlackStream throws
SlackStreamNotDeliveredError with a large pending buffer, the single
raw post could fail (msg_too_long) and drop the unsent tail.

Two changes:

1. deliverPendingStreamFallback now routes through deliverReplies so
   long pendingText is chunked by the normal sender and the fallback
   honors the configured replyToMode / identity.

2. The non-benign streaming-error branch in deliverWithStreaming now
   clears the session via markSlackStreamFallbackDelivered before
   falling back to deliverNormally. Without this, pendingText stays
   populated and the post-loop finalize (stopSlackStream →
   SlackStreamNotDeliveredError → fallback) re-posts the same chunk
   that deliverNormally already sent.

Addresses the three Codex P1 findings on openclaw#70370 about bypassing the
chunked sender, and the related "avoid reposting buffered text after
append fallback" P1 about duplicate delivery. Tests updated to assert
deliverReplies routing (instead of raw postMessage) and a new case
covers the non-benign-error dedup.

Follow-up to openclaw#70370.
Address Codex P1 on openclaw#71124: `markSlackStreamFallbackDelivered` was
clearing `pendingText` before `deliverNormally` ran, so any earlier
buffered chunk was lost. E.g. chunk A buffered in the SDK, then
appending chunk B throws a generic network error → previous fix
dropped A+B and only sent B via `deliverNormally`, silently truncating
the final reply.

Route the full buffered `pendingText` through
`deliverPendingStreamFallback` with a synthetic
`SlackStreamNotDeliveredError`, then skip `deliverNormally` entirely
(pendingText already contains this payload's text, per
`appendSlackStream` accumulating before throw). If the chunked
fallback fails, fall back to `deliverNormally` so at least the current
payload lands.

Test updated to assert the full pendingText ("first buffered\nsecond
payload") gets routed through the chunked sender, not the
chunk-B-only partial send.
@steipete
steipete force-pushed the fix/slack-stream-fallback-chunked branch from 1fb3d9f to 5bd1083 Compare April 24, 2026 21:47
@steipete
steipete merged commit 150053b into openclaw:main Apr 24, 2026
64 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Landed via squash after rebasing onto latest main.

Fixup added:

  • Updated Slack stream fallback comments to describe the normal Slack reply path instead of raw chat.postMessage.
  • Added sender-level coverage proving oversized fallback-sized Slack text is split by the normal Slack sender.
  • Added changelog credit. Thanks @martingarramon!

Proof:

  • pnpm test extensions/slack/src/monitor/message-handler/dispatch.preview-fallback.test.ts extensions/slack/src/monitor/message-handler/dispatch.streaming.test.ts extensions/slack/src/streaming.test.ts extensions/slack/src/send.blocks.test.ts — 57 tests passed.
  • pnpm check:changed — extension typecheck, extension test typecheck, lint, import cycles, 83 Slack extension files / 753 tests passed on latest main.
  • pnpm check — passed.
  • pnpm test — full 70-shard suite passed locally before the final changelog-only rebase.
  • GitHub CI for 5bd1083af01c05bf50f743b7d4e78f1bbee4ac49 — green.

Source SHA: 5bd1083
Merge SHA: 150053b

Angfr95 pushed a commit to Angfr95/openclaw that referenced this pull request Apr 25, 2026
…llow-up to openclaw#70370) (openclaw#71124)

* fix(slack): route stream-fallback delivery through chunked sender

deliverPendingStreamFallback was calling chat.postMessage directly for
err.pendingText, which bypasses the chunked reply path used everywhere
else. For Slack Connect cases where appendSlackStream throws
SlackStreamNotDeliveredError with a large pending buffer, the single
raw post could fail (msg_too_long) and drop the unsent tail.

Two changes:

1. deliverPendingStreamFallback now routes through deliverReplies so
   long pendingText is chunked by the normal sender and the fallback
   honors the configured replyToMode / identity.

2. The non-benign streaming-error branch in deliverWithStreaming now
   clears the session via markSlackStreamFallbackDelivered before
   falling back to deliverNormally. Without this, pendingText stays
   populated and the post-loop finalize (stopSlackStream →
   SlackStreamNotDeliveredError → fallback) re-posts the same chunk
   that deliverNormally already sent.

Addresses the three Codex P1 findings on openclaw#70370 about bypassing the
chunked sender, and the related "avoid reposting buffered text after
append fallback" P1 about duplicate delivery. Tests updated to assert
deliverReplies routing (instead of raw postMessage) and a new case
covers the non-benign-error dedup.

Follow-up to openclaw#70370.

* fix(slack): preserve pending buffered text on non-benign stream errors

Address Codex P1 on openclaw#71124: `markSlackStreamFallbackDelivered` was
clearing `pendingText` before `deliverNormally` ran, so any earlier
buffered chunk was lost. E.g. chunk A buffered in the SDK, then
appending chunk B throws a generic network error → previous fix
dropped A+B and only sent B via `deliverNormally`, silently truncating
the final reply.

Route the full buffered `pendingText` through
`deliverPendingStreamFallback` with a synthetic
`SlackStreamNotDeliveredError`, then skip `deliverNormally` entirely
(pendingText already contains this payload's text, per
`appendSlackStream` accumulating before throw). If the chunked
fallback fails, fall back to `deliverNormally` so at least the current
payload lands.

Test updated to assert the full pendingText ("first buffered\nsecond
payload") gets routed through the chunked sender, not the
chunk-B-only partial send.

* fix(slack): harden stream fallback docs and chunking test (openclaw#71124)

---------

Co-authored-by: Peter Steinberger <[email protected]>
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…llow-up to openclaw#70370) (openclaw#71124)

* fix(slack): route stream-fallback delivery through chunked sender

deliverPendingStreamFallback was calling chat.postMessage directly for
err.pendingText, which bypasses the chunked reply path used everywhere
else. For Slack Connect cases where appendSlackStream throws
SlackStreamNotDeliveredError with a large pending buffer, the single
raw post could fail (msg_too_long) and drop the unsent tail.

Two changes:

1. deliverPendingStreamFallback now routes through deliverReplies so
   long pendingText is chunked by the normal sender and the fallback
   honors the configured replyToMode / identity.

2. The non-benign streaming-error branch in deliverWithStreaming now
   clears the session via markSlackStreamFallbackDelivered before
   falling back to deliverNormally. Without this, pendingText stays
   populated and the post-loop finalize (stopSlackStream →
   SlackStreamNotDeliveredError → fallback) re-posts the same chunk
   that deliverNormally already sent.

Addresses the three Codex P1 findings on openclaw#70370 about bypassing the
chunked sender, and the related "avoid reposting buffered text after
append fallback" P1 about duplicate delivery. Tests updated to assert
deliverReplies routing (instead of raw postMessage) and a new case
covers the non-benign-error dedup.

Follow-up to openclaw#70370.

* fix(slack): preserve pending buffered text on non-benign stream errors

Address Codex P1 on openclaw#71124: `markSlackStreamFallbackDelivered` was
clearing `pendingText` before `deliverNormally` ran, so any earlier
buffered chunk was lost. E.g. chunk A buffered in the SDK, then
appending chunk B throws a generic network error → previous fix
dropped A+B and only sent B via `deliverNormally`, silently truncating
the final reply.

Route the full buffered `pendingText` through
`deliverPendingStreamFallback` with a synthetic
`SlackStreamNotDeliveredError`, then skip `deliverNormally` entirely
(pendingText already contains this payload's text, per
`appendSlackStream` accumulating before throw). If the chunked
fallback fails, fall back to `deliverNormally` so at least the current
payload lands.

Test updated to assert the full pendingText ("first buffered\nsecond
payload") gets routed through the chunked sender, not the
chunk-B-only partial send.

* fix(slack): harden stream fallback docs and chunking test (openclaw#71124)

---------

Co-authored-by: Peter Steinberger <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…llow-up to openclaw#70370) (openclaw#71124)

* fix(slack): route stream-fallback delivery through chunked sender

deliverPendingStreamFallback was calling chat.postMessage directly for
err.pendingText, which bypasses the chunked reply path used everywhere
else. For Slack Connect cases where appendSlackStream throws
SlackStreamNotDeliveredError with a large pending buffer, the single
raw post could fail (msg_too_long) and drop the unsent tail.

Two changes:

1. deliverPendingStreamFallback now routes through deliverReplies so
   long pendingText is chunked by the normal sender and the fallback
   honors the configured replyToMode / identity.

2. The non-benign streaming-error branch in deliverWithStreaming now
   clears the session via markSlackStreamFallbackDelivered before
   falling back to deliverNormally. Without this, pendingText stays
   populated and the post-loop finalize (stopSlackStream →
   SlackStreamNotDeliveredError → fallback) re-posts the same chunk
   that deliverNormally already sent.

Addresses the three Codex P1 findings on openclaw#70370 about bypassing the
chunked sender, and the related "avoid reposting buffered text after
append fallback" P1 about duplicate delivery. Tests updated to assert
deliverReplies routing (instead of raw postMessage) and a new case
covers the non-benign-error dedup.

Follow-up to openclaw#70370.

* fix(slack): preserve pending buffered text on non-benign stream errors

Address Codex P1 on openclaw#71124: `markSlackStreamFallbackDelivered` was
clearing `pendingText` before `deliverNormally` ran, so any earlier
buffered chunk was lost. E.g. chunk A buffered in the SDK, then
appending chunk B throws a generic network error → previous fix
dropped A+B and only sent B via `deliverNormally`, silently truncating
the final reply.

Route the full buffered `pendingText` through
`deliverPendingStreamFallback` with a synthetic
`SlackStreamNotDeliveredError`, then skip `deliverNormally` entirely
(pendingText already contains this payload's text, per
`appendSlackStream` accumulating before throw). If the chunked
fallback fails, fall back to `deliverNormally` so at least the current
payload lands.

Test updated to assert the full pendingText ("first buffered\nsecond
payload") gets routed through the chunked sender, not the
chunk-B-only partial send.

* fix(slack): harden stream fallback docs and chunking test (openclaw#71124)

---------

Co-authored-by: Peter Steinberger <[email protected]>
globalcaos pushed a commit to globalcaos/tinkerclaw that referenced this pull request May 13, 2026
…llow-up to openclaw#70370) (openclaw#71124)

* fix(slack): route stream-fallback delivery through chunked sender

deliverPendingStreamFallback was calling chat.postMessage directly for
err.pendingText, which bypasses the chunked reply path used everywhere
else. For Slack Connect cases where appendSlackStream throws
SlackStreamNotDeliveredError with a large pending buffer, the single
raw post could fail (msg_too_long) and drop the unsent tail.

Two changes:

1. deliverPendingStreamFallback now routes through deliverReplies so
   long pendingText is chunked by the normal sender and the fallback
   honors the configured replyToMode / identity.

2. The non-benign streaming-error branch in deliverWithStreaming now
   clears the session via markSlackStreamFallbackDelivered before
   falling back to deliverNormally. Without this, pendingText stays
   populated and the post-loop finalize (stopSlackStream →
   SlackStreamNotDeliveredError → fallback) re-posts the same chunk
   that deliverNormally already sent.

Addresses the three Codex P1 findings on openclaw#70370 about bypassing the
chunked sender, and the related "avoid reposting buffered text after
append fallback" P1 about duplicate delivery. Tests updated to assert
deliverReplies routing (instead of raw postMessage) and a new case
covers the non-benign-error dedup.

Follow-up to openclaw#70370.

* fix(slack): preserve pending buffered text on non-benign stream errors

Address Codex P1 on openclaw#71124: `markSlackStreamFallbackDelivered` was
clearing `pendingText` before `deliverNormally` ran, so any earlier
buffered chunk was lost. E.g. chunk A buffered in the SDK, then
appending chunk B throws a generic network error → previous fix
dropped A+B and only sent B via `deliverNormally`, silently truncating
the final reply.

Route the full buffered `pendingText` through
`deliverPendingStreamFallback` with a synthetic
`SlackStreamNotDeliveredError`, then skip `deliverNormally` entirely
(pendingText already contains this payload's text, per
`appendSlackStream` accumulating before throw). If the chunked
fallback fails, fall back to `deliverNormally` so at least the current
payload lands.

Test updated to assert the full pendingText ("first buffered\nsecond
payload") gets routed through the chunked sender, not the
chunk-B-only partial send.

* fix(slack): harden stream fallback docs and chunking test (openclaw#71124)

---------

Co-authored-by: Peter Steinberger <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
…llow-up to openclaw#70370) (openclaw#71124)

* fix(slack): route stream-fallback delivery through chunked sender

deliverPendingStreamFallback was calling chat.postMessage directly for
err.pendingText, which bypasses the chunked reply path used everywhere
else. For Slack Connect cases where appendSlackStream throws
SlackStreamNotDeliveredError with a large pending buffer, the single
raw post could fail (msg_too_long) and drop the unsent tail.

Two changes:

1. deliverPendingStreamFallback now routes through deliverReplies so
   long pendingText is chunked by the normal sender and the fallback
   honors the configured replyToMode / identity.

2. The non-benign streaming-error branch in deliverWithStreaming now
   clears the session via markSlackStreamFallbackDelivered before
   falling back to deliverNormally. Without this, pendingText stays
   populated and the post-loop finalize (stopSlackStream →
   SlackStreamNotDeliveredError → fallback) re-posts the same chunk
   that deliverNormally already sent.

Addresses the three Codex P1 findings on openclaw#70370 about bypassing the
chunked sender, and the related "avoid reposting buffered text after
append fallback" P1 about duplicate delivery. Tests updated to assert
deliverReplies routing (instead of raw postMessage) and a new case
covers the non-benign-error dedup.

Follow-up to openclaw#70370.

* fix(slack): preserve pending buffered text on non-benign stream errors

Address Codex P1 on openclaw#71124: `markSlackStreamFallbackDelivered` was
clearing `pendingText` before `deliverNormally` ran, so any earlier
buffered chunk was lost. E.g. chunk A buffered in the SDK, then
appending chunk B throws a generic network error → previous fix
dropped A+B and only sent B via `deliverNormally`, silently truncating
the final reply.

Route the full buffered `pendingText` through
`deliverPendingStreamFallback` with a synthetic
`SlackStreamNotDeliveredError`, then skip `deliverNormally` entirely
(pendingText already contains this payload's text, per
`appendSlackStream` accumulating before throw). If the chunked
fallback fails, fall back to `deliverNormally` so at least the current
payload lands.

Test updated to assert the full pendingText ("first buffered\nsecond
payload") gets routed through the chunked sender, not the
chunk-B-only partial send.

* fix(slack): harden stream fallback docs and chunking test (openclaw#71124)

---------

Co-authored-by: Peter Steinberger <[email protected]>
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
…llow-up to openclaw#70370) (openclaw#71124)

* fix(slack): route stream-fallback delivery through chunked sender

deliverPendingStreamFallback was calling chat.postMessage directly for
err.pendingText, which bypasses the chunked reply path used everywhere
else. For Slack Connect cases where appendSlackStream throws
SlackStreamNotDeliveredError with a large pending buffer, the single
raw post could fail (msg_too_long) and drop the unsent tail.

Two changes:

1. deliverPendingStreamFallback now routes through deliverReplies so
   long pendingText is chunked by the normal sender and the fallback
   honors the configured replyToMode / identity.

2. The non-benign streaming-error branch in deliverWithStreaming now
   clears the session via markSlackStreamFallbackDelivered before
   falling back to deliverNormally. Without this, pendingText stays
   populated and the post-loop finalize (stopSlackStream →
   SlackStreamNotDeliveredError → fallback) re-posts the same chunk
   that deliverNormally already sent.

Addresses the three Codex P1 findings on openclaw#70370 about bypassing the
chunked sender, and the related "avoid reposting buffered text after
append fallback" P1 about duplicate delivery. Tests updated to assert
deliverReplies routing (instead of raw postMessage) and a new case
covers the non-benign-error dedup.

Follow-up to openclaw#70370.

* fix(slack): preserve pending buffered text on non-benign stream errors

Address Codex P1 on openclaw#71124: `markSlackStreamFallbackDelivered` was
clearing `pendingText` before `deliverNormally` ran, so any earlier
buffered chunk was lost. E.g. chunk A buffered in the SDK, then
appending chunk B throws a generic network error → previous fix
dropped A+B and only sent B via `deliverNormally`, silently truncating
the final reply.

Route the full buffered `pendingText` through
`deliverPendingStreamFallback` with a synthetic
`SlackStreamNotDeliveredError`, then skip `deliverNormally` entirely
(pendingText already contains this payload's text, per
`appendSlackStream` accumulating before throw). If the chunked
fallback fails, fall back to `deliverNormally` so at least the current
payload lands.

Test updated to assert the full pendingText ("first buffered\nsecond
payload") gets routed through the chunked sender, not the
chunk-B-only partial send.

* fix(slack): harden stream fallback docs and chunking test (openclaw#71124)

---------

Co-authored-by: Peter Steinberger <[email protected]>
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
…llow-up to openclaw#70370) (openclaw#71124)

* fix(slack): route stream-fallback delivery through chunked sender

deliverPendingStreamFallback was calling chat.postMessage directly for
err.pendingText, which bypasses the chunked reply path used everywhere
else. For Slack Connect cases where appendSlackStream throws
SlackStreamNotDeliveredError with a large pending buffer, the single
raw post could fail (msg_too_long) and drop the unsent tail.

Two changes:

1. deliverPendingStreamFallback now routes through deliverReplies so
   long pendingText is chunked by the normal sender and the fallback
   honors the configured replyToMode / identity.

2. The non-benign streaming-error branch in deliverWithStreaming now
   clears the session via markSlackStreamFallbackDelivered before
   falling back to deliverNormally. Without this, pendingText stays
   populated and the post-loop finalize (stopSlackStream →
   SlackStreamNotDeliveredError → fallback) re-posts the same chunk
   that deliverNormally already sent.

Addresses the three Codex P1 findings on openclaw#70370 about bypassing the
chunked sender, and the related "avoid reposting buffered text after
append fallback" P1 about duplicate delivery. Tests updated to assert
deliverReplies routing (instead of raw postMessage) and a new case
covers the non-benign-error dedup.

Follow-up to openclaw#70370.

* fix(slack): preserve pending buffered text on non-benign stream errors

Address Codex P1 on openclaw#71124: `markSlackStreamFallbackDelivered` was
clearing `pendingText` before `deliverNormally` ran, so any earlier
buffered chunk was lost. E.g. chunk A buffered in the SDK, then
appending chunk B throws a generic network error → previous fix
dropped A+B and only sent B via `deliverNormally`, silently truncating
the final reply.

Route the full buffered `pendingText` through
`deliverPendingStreamFallback` with a synthetic
`SlackStreamNotDeliveredError`, then skip `deliverNormally` entirely
(pendingText already contains this payload's text, per
`appendSlackStream` accumulating before throw). If the chunked
fallback fails, fall back to `deliverNormally` so at least the current
payload lands.

Test updated to assert the full pendingText ("first buffered\nsecond
payload") gets routed through the chunked sender, not the
chunk-B-only partial send.

* fix(slack): harden stream fallback docs and chunking test (openclaw#71124)

---------

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants