Skip to content

Telegram message-tool-only turns can still emit empty-response fallback via skipped delivery lane #90091

Description

@pfrederiksen

Summary

This is a follow-up to #90076, which was closed as already solved in main.

The original issue is not fully solved. Current main and v2026.6.1 already suppress one silent fallback path for message_tool_only turns, but the live failure came through the separate empty-response/failure fallback branch:

!deliverySummary.delivered &&
  (deliverySummary.skippedNonSilent > 0 || deliverySummary.failedNonSilent > 0)

That branch still ignores sourceReplyDeliveryMode === "message_tool_only", so a Telegram group turn can successfully send the visible reply through message(action="send"), finish with exact NO_REPLY, and still get a later generic fallback:

No response generated. Please try again.

Environment

  • OpenClaw version observed live: OpenClaw 2026.6.1 (2e08f0f)
  • Current origin/main checked before filing: 179ff9b4230c003c1e08cc356fac93fc7c849c6d
  • Channel: Telegram group
  • Source reply mode: message-tool-only group-visible replies

Live Evidence

From a real Telegram group session:

  • The agent sent a successful visible reply using message(action="send").
  • The final assistant payload was exact NO_REPLY.
  • The transcript then received two delivery-mirror fallback assistant messages:
    • 2026-06-04T00:07:02.309Z: provider openclaw, model delivery-mirror, text No response generated. Please try again.
    • 2026-06-04T00:07:32.129Z: provider openclaw, model delivery-mirror, text No response generated. Please try again.
  • The user reset the Telegram group session shortly afterward at 2026-06-04T00:07:43.903Z because the turn looked broken.

Local private evidence paths available to the reporter:

  • Reset transcript: /root/.openclaw/agents/main/sessions/f61684d0-37d3-4d7d-be9d-56f8fbb12098.jsonl.reset.2026-06-04T00-07-43.733Z
  • Reset command log: /root/.openclaw/logs/commands.log

Those paths are intentionally included as reporter-local breadcrumbs, not public repro requirements.

Why #90076 Closure Was Incomplete

The closure comment on #90076 correctly identified this existing guard:

suppressSilentReplyFallback =
  turnResult.dispatchResult.sourceReplyDeliveryMode === "message_tool_only";

However, current main still computes the failure/empty-response fallback without that guard:

const shouldSendFailureFallback =
  !isRoomEvent &&
  (dispatchError ||
    (!deliverySummary.delivered &&
      (deliverySummary.skippedNonSilent > 0 || deliverySummary.failedNonSilent > 0)));

So the already-implemented suppression covers the silent fallback branch, but not the branch that actually produced the live No response generated. Please try again. messages.

Expected

For a Telegram group turn where source delivery is message_tool_only:

  • A successful message(action="send") visible reply should satisfy the user-visible response requirement.
  • Exact NO_REPLY final text should remain silent.
  • Telegram should not emit the generic empty-response fallback from either fallback branch.

Actual

Telegram can still emit No response generated. Please try again. after a successful message-tool visible reply plus NO_REPLY final when the automatic Telegram delivery lane records a non-silent skipped/failed final payload.

Suggested Fix

Apply the existing message-tool-only suppression guard to the failure/empty-response fallback branch too. Conceptually:

const shouldSendFailureFallback =
  !isRoomEvent &&
  !suppressSilentReplyFallback &&
  (dispatchError ||
    (!deliverySummary.delivered &&
      (deliverySummary.skippedNonSilent > 0 || deliverySummary.failedNonSilent > 0)));

There was a previous PR with this shape, #90080, but it was closed while sorting out whether #90076 was already fixed. The useful part of that PR was the source-level regression for a message_tool_only turn where final text is skipped/silent and the automatic final text is skipped non-silent; before the guard that shape is eligible for the empty-response fallback.

Impact

The user sees a successful reply followed by one or more generic failure messages, which makes the Telegram session appear wedged and can prompt unnecessary /reset, losing continuity.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions