Description
When channels.telegram.streamMode is set to "block" or "partial", tool error warnings (⚠️ ... failed) overwrite the previous draft message instead of being sent as a separate message.
Steps to Reproduce
- Set
channels.telegram.streamMode: "block" (or "partial")
- Trigger a response that involves a tool call
- Have the tool call fail (e.g., network error, timeout)
- Observe that the error message replaces the draft preview message content
Expected Behavior
Error messages should be sent as new messages, not edit the existing draft preview message. The draft should either be finalized with the last valid content or cleared, and the error sent separately.
Actual Behavior
The error reply (isError: true) goes through the same deliver callback and calls editMessageText on the draft message ID, replacing whatever content was previously displayed.
Root Cause (from source analysis)
In the Telegram reply dispatcher (pi-embedded-*.js), the deliver callback for info.kind === "final" checks if the text fits within draftMaxChars and edits the preview message. Error replies also hit this path because they are included in replyItems with isError: true but are not excluded from the draft-edit finalization logic.
Relevant code path:
replyItems.push({ text: warningText, isError: true }) (line ~64588)
- Draft edit finalization at line ~55494-55504: no check for
payload.isError
Suggested Fix
In the deliver callback, skip the draft preview edit path when payload.isError === true, forcing error messages to be sent as new messages via deliverReplies.
Environment
- OpenClaw: 2026.2.15
- Channel: Telegram
- streamMode: block
- OS: macOS 26.2 (arm64)
Description
When
channels.telegram.streamModeis set to"block"or"partial", tool error warnings (⚠️ ... failed) overwrite the previous draft message instead of being sent as a separate message.Steps to Reproduce
channels.telegram.streamMode: "block"(or"partial")Expected Behavior
Error messages should be sent as new messages, not edit the existing draft preview message. The draft should either be finalized with the last valid content or cleared, and the error sent separately.
Actual Behavior
The error reply (
isError: true) goes through the samedelivercallback and callseditMessageTexton the draft message ID, replacing whatever content was previously displayed.Root Cause (from source analysis)
In the Telegram reply dispatcher (
pi-embedded-*.js), thedelivercallback forinfo.kind === "final"checks if the text fits withindraftMaxCharsand edits the preview message. Error replies also hit this path because they are included inreplyItemswithisError: truebut are not excluded from the draft-edit finalization logic.Relevant code path:
replyItems.push({ text: warningText, isError: true })(line ~64588)payload.isErrorSuggested Fix
In the
delivercallback, skip the draft preview edit path whenpayload.isError === true, forcing error messages to be sent as new messages viadeliverReplies.Environment