openclaw - ✅(Solved) Fix Telegram channel: messages truncated mid-word when default "partial" streaming finaliser doesn't fire [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#71525Fetched 2026-04-26 05:11:56
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
closed ×1cross-referenced ×1

Telegram-channel outbound messages get permanently truncated mid-word when the default streaming.mode: "partial" preview loop terminates without firing a final editMessageText. The message is left frozen at whatever the last successful streaming edit captured, with no recovery and no error surfaced to the user.

We hit this on three production Brain bots (Spoons-Brain, BDC-Brain, Klara-Brain) in an active multi-bot Telegram group on 2026-04-25. Every reply was getting cut off mid-token until we set streaming.mode: "off".

Error Message

Telegram-channel outbound messages get permanently truncated mid-word when the default streaming.mode: "partial" preview loop terminates without firing a final editMessageText. The message is left frozen at whatever the last successful streaming edit captured, with no recovery and no error surfaced to the user.

  • No error log from the streaming preview code.
  • A swallowed error in the streaming loop that skips finalisation. That field is not in the strict zod schema for the Telegram channel. Adding it causes the entire channels.telegram block to be silently rejected at startup and the channel falls back to all defaults — including streaming.mode: "partial". No warning, no error log. We spent a non-trivial amount of time chasing this because the fix appeared to revert on every restart when it was actually being silently dropped.

Root Cause

Likely root cause

Fix Action

Fix / Workaround

Workaround (and the gotcha that bit us)

Happy to provide more diagnostic detail or test patches if useful.

PR fix notes

PR #71554: Fix: telegram preview finalization recovery, issue #71525

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2–5 bullets:

If this PR fixes a plugin beta-release blocker, title it fix(<plugin-id>): beta blocker - <summary> and link the matching Beta blocker: <plugin-name> - <summary> issue labeled beta-blocker. Contributors cannot label PRs, so the title is the PR-side signal for maintainers and automation.

  • Problem: Telegram could retain an incomplete preview message when final preview editing failed with an ambiguous error.
  • Why it matters: Users could see a truncated final answer instead of the completed response.
  • What changed: When the retained preview is a known incomplete prefix of the final answer, Telegram delivery now falls back to sending the final text normally.
  • What did NOT change (scope boundary): This does not change Telegram streaming defaults, preview creation, missing-message handling, or broader channel delivery behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #71525
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write N/A. If the cause is unclear, write Unknown.

  • Root cause: Ambiguous Telegram final edit failures were always treated as unsafe to retry, so the existing preview was retained to avoid duplicate final answers.
  • Missing detection / guardrail: There was no check for the case where the retained preview was clearly incomplete because it was a strict prefix of the final text.
  • Contributing context (if known): The previous duplicate-avoidance path was correct for ambiguous successful edits, but too conservative for known-incomplete previews.

Regression Test Plan (if applicable)

For bug fixes or regressions, name the smallest reliable test coverage that should catch this. Otherwise write N/A.

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
    • Target test or file: extensions/telegram/src/lane-delivery.test.ts
    • Scenario the test should lock in: Existing Telegram preview has partial text, final edit fails ambiguously, and the partial text is an incomplete prefix of the final answer.
    • Why this is the smallest reliable guardrail: The lane delivery seam directly owns the ambiguous edit failure decision without needing live Telegram network calls.
    • Existing test that already covers this (if any): Existing ambiguous edit tests covered preview retention but not the incomplete-prefix fallback case.
    • If no new test is added, why not: N/A

User-visible / Behavior Changes

Telegram users are less likely to be left with a truncated preview after final answer delivery when Telegram returns an ambiguous edit failure. Legacy Telegram streaming config docs/help text was clarified. No defaults changed.

Diagram (if applicable)

For UI changes or non-trivial logic flows, include a small ASCII diagram reviewers can scan quickly. Otherwise write N/A.

  Before:
  [final answer ready] -> [Telegram edit fails ambiguously] -> [retain incomplete preview]

  After:
  [final answer ready] -> [Telegram edit fails ambiguously] -> [preview is incomplete prefix] -> [send final answer normally]

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS local workspace
  • Runtime/container: pnpm / Node local runtime
  • Model/provider: N/A
  • Integration/channel (if any): Telegram
  • Relevant config (redacted): Telegram preview streaming with an existing partial preview message

Steps

  1. Create an existing Telegram answer preview whose text is a partial prefix of the final answer.
  2. Simulate final preview edit failure with an ambiguous error such as 500: preview edit failed.
  3. Finalize the answer through the Telegram lane delivery path.

Expected

  • The final answer is sent normally instead of retaining the incomplete preview.

Actual

  • Before this fix, the incomplete preview was retained to avoid possible duplicate delivery.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
    • Added regression coverage for ambiguous final edit failure with incomplete preview prefix.
    • Verified existing ambiguous edit retention behavior still remains covered.
    • Verified Telegram preview-related tests.
    • Verified config/doctor legacy streaming docs-related tests.
  • Edge cases checked:
    • Missing preview message still falls back.
    • Ambiguous edit failure still retains when the preview is not known-incomplete.
  • What you did not verify:
    • Live Telegram bot delivery against the real Telegram API.

Validation run:

pnpm test extensions/telegram/src/lane-delivery.test.ts pnpm test extensions/telegram/src/bot-message-dispatch.test.ts extensions/telegram/src/lane-delivery.test.ts extensions/telegram/src/draft-stream.test.ts pnpm test src/commands/doctor-legacy-config.test.ts extensions/telegram/src/doctor.test.ts src/config/validation.allowed-values.test.ts pnpm check:changed pnpm build

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: A final answer could be sent after an ambiguous edit error even if Telegram actually applied the edit.
    • Mitigation: The fallback is limited to cases where the retained preview is a strict incomplete prefix of the final text, which indicates retaining it would leave a visibly incomplete answer.

Built with Codex

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/channels/telegram.md (modified, +1/-1)
  • docs/concepts/streaming.md (modified, +1/-1)
  • extensions/telegram/src/config-ui-hints.ts (modified, +1/-1)
  • extensions/telegram/src/lane-delivery-text-deliverer.ts (modified, +18/-1)
  • extensions/telegram/src/lane-delivery.test.ts (modified, +39/-1)
  • src/config/bundled-channel-config-metadata.generated.ts (modified, +1/-1)

Code Example

dist/extensions/telegram/preview-streaming-CWdgSb-e.js

---

resolveTelegramPreviewStreamMode(params, "partial")

---

{
  "channels": {
    "telegram": {
      "streaming": { "mode": "off" }
    }
  }
}

---

"channels": {
  "telegram": {
    "streamMode": "off"   // SILENTLY REJECTED
  }
}
RAW_BUFFERClick to expand / collapse

Summary

Telegram-channel outbound messages get permanently truncated mid-word when the default streaming.mode: "partial" preview loop terminates without firing a final editMessageText. The message is left frozen at whatever the last successful streaming edit captured, with no recovery and no error surfaced to the user.

We hit this on three production Brain bots (Spoons-Brain, BDC-Brain, Klara-Brain) in an active multi-bot Telegram group on 2026-04-25. Every reply was getting cut off mid-token until we set streaming.mode: "off".

Reproduce

  • Bot configured with default Telegram channel settings (no explicit streaming block).
  • Active group chat with multiple bots and an assistant that produces output in the shape text → tool_call → more text (i.e. the assistant emits text, calls a tool, then emits more text in the same turn).
  • After a handful of replies, outbound messages start being truncated mid-word. Subsequent assistant turns may or may not be fine. Restarts don't help — the next problematic turn truncates again.

Symptom

  • Outbound Telegram message frozen at whatever state the last successful editMessageText captured.
  • No final editMessageText with the complete assistant text.
  • Bot internal logs show the assistant turn completed fully — only the Telegram-side message is incomplete.
  • No error log from the streaming preview code.

Likely root cause

The default streaming.mode is set to "partial" in the bundled distribution at:

dist/extensions/telegram/preview-streaming-CWdgSb-e.js

via:

resolveTelegramPreviewStreamMode(params, "partial")

The streaming-preview loop doesn't appear to guarantee a final flush on every turn-shape. Suspected triggers:

  • Telegram rate-limiting an editMessageText call (loop backs off and never resumes).
  • Assistant emits a tool call mid-turn, then continues text in what the streamer treats as a fresh stream — original message never finalised.
  • A swallowed error in the streaming loop that skips finalisation.

In all of these cases the partially-edited Telegram message is left orphaned forever.

Workaround (and the gotcha that bit us)

In openclaw.json:

{
  "channels": {
    "telegram": {
      "streaming": { "mode": "off" }
    }
  }
}

This sends the assistant turn as a single sendMessage once it's complete. No live token preview, but reliable.

⚠️ Schema gotcha: older docs / community snippets suggest a top-level streamMode field:

"channels": {
  "telegram": {
    "streamMode": "off"   // SILENTLY REJECTED
  }
}

That field is not in the strict zod schema for the Telegram channel. Adding it causes the entire channels.telegram block to be silently rejected at startup and the channel falls back to all defaults — including streaming.mode: "partial". No warning, no error log. We spent a non-trivial amount of time chasing this because the fix appeared to revert on every restart when it was actually being silently dropped.

Recommendations

  1. Change the Telegram default to "off" until the streaming finaliser is bulletproof. Live token preview is a nice-to-have; truncated messages are a correctness bug.
  2. OR add a finalisation watchdog: regardless of streaming-loop state, always fire a final editMessageText with the full assistant text when the assistant turn ends. The current code clearly has paths where this doesn't happen.
  3. Either accept legacy streamMode as an alias OR fail loudly when an unknown channel key is seen. Silently rejecting the whole channel block is the worst possible UX — config silently doesn't apply, no log, defaults take over.

Environment

  • OpenClaw bundled distribution (running alpine/openclaw:latest-style image on K3s, also reproduced on openclaw npm package).
  • Telegram bot in active multi-bot group chat.
  • Assistant: anthropic/claude-opus-4-7 with tool use enabled.

Happy to provide more diagnostic detail or test patches if useful.

extent analysis

TL;DR

Disable the default streaming.mode: "partial" by setting streaming.mode: "off" in the Telegram channel configuration to prevent message truncation.

Guidance

  • To fix the issue, update the openclaw.json configuration file with the correct syntax: "channels": { "telegram": { "streaming": { "mode": "off" } } }.
  • Verify that the streaming.mode is correctly set by checking the bot's behavior and ensuring that messages are no longer truncated.
  • Be aware of the schema gotcha: using the top-level streamMode field will silently reject the entire channels.telegram block, causing the channel to fall back to defaults.
  • Consider adding a finalisation watchdog to ensure that a final editMessageText is always fired with the full assistant text when the assistant turn ends.

Example

No code snippet is provided as the issue is related to configuration and not code.

Notes

The provided workaround disables live token preview but ensures reliable message delivery. The root cause of the issue is related to the default streaming.mode and the lack of a finalisation mechanism in the streaming loop.

Recommendation

Apply the workaround by setting streaming.mode: "off" in the Telegram channel configuration. This is a reliable solution that prevents message truncation, although it disables live token preview.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING