openclaw - ✅(Solved) Fix Telegram plugin: outbound media path (sendVoice / sendAudio / sendDocument / ...) emits no success log line [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#68770Fetched 2026-04-19 15:07:49
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
cross-referenced ×1referenced ×1

The Telegram plugin writes a telegram sendMessage ok chat=... message=... log line for every text send, but the media path (sendVoice, sendAudio, sendDocument, sendVideo, etc.) has no equivalent log line. This breaks observability for TTS-backed voice notes and any other media-bearing replies: grep sendVoice ~/.openclaw/logs/gateway.log returns zero hits even when voice notes have actually been delivered, and the only on-disk evidence is the file left behind in ~/.openclaw/media/outbound/.

When combined with the TTS auto-trigger bug (sibling issue: TTS directive parser is markdown-blind), this made it essentially impossible for the assistant to detect that it had just sent a voice note to the user — it checked the gateway log as it should, saw no sendVoice entry, and confidently replied "I didn't send a voice note" three times in a row despite the user insisting otherwise.

Error Message

Error paths for sendVoice / sendAudio do appear in gateway.err.log (e.g. sendVoice failed: Network request for 'sendVoice' failed!), so the observability imbalance is one-sided: we see media failures but not media successes.

Root Cause

The Telegram plugin writes a telegram sendMessage ok chat=... message=... log line for every text send, but the media path (sendVoice, sendAudio, sendDocument, sendVideo, etc.) has no equivalent log line. This breaks observability for TTS-backed voice notes and any other media-bearing replies: grep sendVoice ~/.openclaw/logs/gateway.log returns zero hits even when voice notes have actually been delivered, and the only on-disk evidence is the file left behind in ~/.openclaw/media/outbound/.

When combined with the TTS auto-trigger bug (sibling issue: TTS directive parser is markdown-blind), this made it essentially impossible for the assistant to detect that it had just sent a voice note to the user — it checked the gateway log as it should, saw no sendVoice entry, and confidently replied "I didn't send a voice note" three times in a row despite the user insisting otherwise.

Fix Action

Fixed

PR fix notes

PR #68836: fix(telegram): add success log lines for media send operations [AI-assisted]

Description (problem / solution / changelog)

AI-assisted: yes (Antigravity).

Summary

Add missing success log lines for all six Telegram media send operations: sendAnimation, sendPhoto, sendVideo, sendVoice, sendAudio, and sendDocument.

The text path (sendMessage) already emits elegram sendMessage ok chat=... message=... on success, but none of the media paths had equivalent log output. This made it impossible to confirm media delivery via gateway logs — grep sendVoice ~/.openclaw/logs/gateway.log returned zero hits even when voice notes were actually delivered.

What Changed

  • Added untime.log?.(...) after each successful media API call in deliverMediaReply(), matching the existing sendMessage ok format:
    • elegram sendAnimation ok chat=<id> message=<id>
    • elegram sendPhoto ok chat=<id> message=<id>
    • elegram sendVideo ok chat=<id> message=<id>
    • elegram sendVoice ok chat=<id> message=<id>
    • elegram sendAudio ok chat=<id> message=<id>
    • elegram sendDocument ok chat=<id> message=<id>

Related Issue

Closes #68770

Validation

  • Fully tested: all 31 existing delivery.test.ts tests pass
  • All 80 send.test.ts tests pass
  • Pure observability change — no logic modified, zero regression risk
  • Uses optional chaining ( untime.log?.()) consistent with existing patterns

Changed files

  • extensions/telegram/src/bot/delivery.replies.ts (modified, +6/-0)

Code Example

[telegram] sendVoice ok chat=<chatId> message=<messageId> file=<path>
[telegram] sendAudio ok chat=<chatId> message=<messageId> file=<path>
[telegram] sendDocument ok chat=<chatId> message=<messageId> file=<path>

---

const result = await sendMedia(mediaSender.label, mediaSender.sender);
const mediaMessageId = resolveTelegramMessageIdOrThrow(result, "media send");

---

runtime.log?.(`telegram sendMessage ok chat=${chatId} message=${res.message_id} (plain)`);
// ...
runtime.log?.(`telegram sendMessage ok chat=${chatId} message=${res.message_id}`);

---

runtime.log?.(
  `telegram send${capitalize(mediaSender.label)} ok chat=${resolvedChatId} message=${mediaMessageId}`
);

---

runtime.log?.(`telegram ${mediaSender.label} ok chat=${resolvedChatId} message=${mediaMessageId}`);
RAW_BUFFERClick to expand / collapse

Summary

The Telegram plugin writes a telegram sendMessage ok chat=... message=... log line for every text send, but the media path (sendVoice, sendAudio, sendDocument, sendVideo, etc.) has no equivalent log line. This breaks observability for TTS-backed voice notes and any other media-bearing replies: grep sendVoice ~/.openclaw/logs/gateway.log returns zero hits even when voice notes have actually been delivered, and the only on-disk evidence is the file left behind in ~/.openclaw/media/outbound/.

When combined with the TTS auto-trigger bug (sibling issue: TTS directive parser is markdown-blind), this made it essentially impossible for the assistant to detect that it had just sent a voice note to the user — it checked the gateway log as it should, saw no sendVoice entry, and confidently replied "I didn't send a voice note" three times in a row despite the user insisting otherwise.

Environment

  • OpenClaw 2026.4.15 (041266a)
  • Telegram plugin (bundled)
  • Node 25.7.0, macOS 26.4.1

Reproduction

  1. messages.tts.auto = "tagged" with a working ElevenLabs provider.
  2. Cause a TTS-triggering reply (see sibling issue) so the Telegram plugin ends up in the media path with audioAsVoice=true.
  3. Tail ~/.openclaw/logs/gateway.log — only a sendMessage line from the text sibling appears (if any); no sendVoice ok / sendAudio ok / sendMedia ok / voice ok line.
  4. ls ~/.openclaw/media/outbound/ — the MP3 file exists with a timestamp matching the delivery moment.

Expected behavior

Outbound media delivery should emit a log line parallel to sendMessage ok, containing at least:

  • media kind (voice, audio, document, video, video_note, photo, ...)
  • chat id
  • Telegram message_id
  • (optionally) local media file path or media id, duration, size

Example target format:

[telegram] sendVoice ok chat=<chatId> message=<messageId> file=<path>
[telegram] sendAudio ok chat=<chatId> message=<messageId> file=<path>
[telegram] sendDocument ok chat=<chatId> message=<messageId> file=<path>

This keeps log-based diagnostics working and matches the existing sendMessage ok line in delivery-AYrG1NE_.js.

Actual behavior

dist/extensions/telegram/send-DlzbQJQs.js builds a mediaSender closure around api.sendVoice / sendAudio / sendDocument / sendVideo / sendVideoNote / sendPhoto and then awaits it via sendMedia(mediaSender.label, mediaSender.sender) at line 804:

const result = await sendMedia(mediaSender.label, mediaSender.sender);
const mediaMessageId = resolveTelegramMessageIdOrThrow(result, "media send");

resolveTelegramMessageIdOrThrow only throws on missing id — it does not call runtime.log?.(...). No other call site emits an info log for successful media sends; only sendMessage in delivery-AYrG1NE_.js:91,115 does:

runtime.log?.(`telegram sendMessage ok chat=${chatId} message=${res.message_id} (plain)`);
// ...
runtime.log?.(`telegram sendMessage ok chat=${chatId} message=${res.message_id}`);

Error paths for sendVoice / sendAudio do appear in gateway.err.log (e.g. sendVoice failed: Network request for 'sendVoice' failed!), so the observability imbalance is one-sided: we see media failures but not media successes.

Impact

  • Incident investigation is harder: the on-disk MP3 in media/outbound/ is the only reliable signal that a voice note was delivered.
  • Users relying on log-based audits to verify that the agent did / did not deliver media get a misleading picture.
  • In my case, three consecutive confident denials ("I did not send a voice note") based on grep sendVoice gateway.log → 0.

Proposed fix

In dist/extensions/telegram/send-DlzbQJQs.js around line 804 (after recordSentMessage / recordChannelActivity), add:

runtime.log?.(
  `telegram send${capitalize(mediaSender.label)} ok chat=${resolvedChatId} message=${mediaMessageId}`
);

or, to match the existing message line format exactly:

runtime.log?.(`telegram ${mediaSender.label} ok chat=${resolvedChatId} message=${mediaMessageId}`);

(Any consistent format works; the important part is that the log line exists for each successful media send.)

Happy to open a PR.

extent analysis

TL;DR

Add a log line for successful media sends in the Telegram plugin to match the existing sendMessage ok line format.

Guidance

  • The issue is caused by the lack of a log line for successful media sends, making it difficult to track media delivery.
  • To fix this, add a log line after the sendMedia call in dist/extensions/telegram/send-DlzbQJQs.js using runtime.log?.().
  • The log line should include the media kind, chat id, and Telegram message id, similar to the existing sendMessage ok line.
  • The proposed fix suggests adding the following line: runtime.log?.(telegram ${mediaSender.label} ok chat=${resolvedChatId} message=${mediaMessageId});

Example

const result = await sendMedia(mediaSender.label, mediaSender.sender);
const mediaMessageId = resolveTelegramMessageIdOrThrow(result, "media send");
runtime.log?.(`telegram ${mediaSender.label} ok chat=${resolvedChatId} message=${mediaMessageId}`);

Notes

  • The fix should be applied to the dist/extensions/telegram/send-DlzbQJQs.js file, around line 804.
  • The log line format can be adjusted to match the existing sendMessage ok line format, but the important part is that the log line exists for each successful media send.

Recommendation

Apply the proposed workaround by adding the log line for successful media sends, as it provides a consistent and reliable way to track media delivery.

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…

FAQ

Expected behavior

Outbound media delivery should emit a log line parallel to sendMessage ok, containing at least:

  • media kind (voice, audio, document, video, video_note, photo, ...)
  • chat id
  • Telegram message_id
  • (optionally) local media file path or media id, duration, size

Example target format:

[telegram] sendVoice ok chat=<chatId> message=<messageId> file=<path>
[telegram] sendAudio ok chat=<chatId> message=<messageId> file=<path>
[telegram] sendDocument ok chat=<chatId> message=<messageId> file=<path>

This keeps log-based diagnostics working and matches the existing sendMessage ok line in delivery-AYrG1NE_.js.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Telegram plugin: outbound media path (sendVoice / sendAudio / sendDocument / ...) emits no success log line [1 pull requests, 1 participants]