Skip to content

[Bug] Gateway swallows user-visible reply when an agent's exec stdout matches "configuration file" — replies=2 puts ⚠️ 🛠️ first, the actual reply second #96239

Description

@jooey

[Bug] Gateway swallows user-visible reply when an agent's exec stdout matches "configuration file" — replies=2 puts ⚠️ 🛠️ first, the actual reply second

Environment

  • OpenClaw version: 2026.6.10-beta.2 (this is the version we observed the bug on; we have not bisected earlier versions)
  • Feishu plugin: @openclaw/[email protected]
  • Channel: Feishu DM, single account (feishu[tester])
  • Model that produced the run: zai/glm-5.2
  • Host: macOS 15.5.0, Node v26.3.0
  • Observed at: 2026-06-24 08:32–08:34 Asia/Shanghai (tester run); a second instance at 09:21–09:23 in the same DM with the same replies=2 shape

Summary

When an agent's exec step produces stdout that contains the substring configuration file at <path>, the gateway populates trace.artifacts.data.lastToolError with that stdout and sets mutatingAction: true. The turn's finalStatus is success and every item completes, but the channel still receives replies=2 — the first reply is a ⚠️ 🛠️ warning card referencing the exec step, and the second reply is the agent's actual final text.

From the user's perspective in the Feishu DM, the warning card sits above the actual reply in the conversation list. The user opens the DM, sees only the warning, and concludes the agent "errored and dropped the message" — even though the real reply IS delivered, just visually displaced.

This affects the user in two ways:

  1. For runs the user is waiting on (the tester's 8:32 case): the user thinks the agent errored and re-prompts, producing duplicate work and a duplicate replies=2 for the follow-up turn.
  2. For the user's own follow-up messages in the same DM (the 9:21 case below): the user sends a short message, the agent replies with a brief text, but again replies=2 is reported, and the user only sees the warning card. The actual agent reply is delivered as the second card and is not visible at the top of the DM.

We do not have evidence yet that the second pattern is triggered by an exec step with the same stdout shape — we are reporting both instances because the observable symptom (replies=2, warning card first, real reply second) is the same. Both could plausibly be the same gateway behavior surfacing warnings for two different underlying conditions; we have not bisected to confirm.

First observed instance (08:32–08:34, tester)

During a multi-tool agent turn, one of the agent's exec steps ran cat ~/Library/Application Support/ngrok/ngrok.yml. The command succeeded and its stdout began with the literal text Valid configuration file at /Users/penny/Library/Application Support/ngrok/ngrok.yml (this is a normal ngrok startup/log message, not an error).

After the turn completed, the gateway's trace.artifacts.data.lastToolError was populated with:

{
  "toolName": "exec",
  "meta": "run # → print text",
  "error": "Valid configuration file at /Users/penny/Library/Application Support/ngrok/ngrok.yml",
  "mutatingAction": true,
  "actionFingerprint": "tool=exec|meta=run # → print text"
}

The turn's finalStatus was success (all 26 items started and completed). However, the Feishu channel received replies=2 from the gateway instead of replies=1. From the user's perspective in the Feishu DM, the first card was a ⚠️ 🛠️ warning referencing the cat step, and the second card was the agent's actual final reply containing the URLs the user asked for. The warning card sits above the reply in the DM list, so at a glance the user sees "agent just errored".

Second observed instance (09:21–09:23, config agent, no exec trigger found)

2026-06-24T09:21:52.156+08:00 [feishu] feishu[config]: dispatching to agent
2026-06-24T09:21:58.597+08:00 [feishu] feishu[config] Started streaming: cardId=7654766098637851612
... <agent does its work, does NOT visibly invoke an exec step with "configuration file" stdout at this point, but we have not pulled the trajectory for this run yet> ...
2026-06-24T09:23:23.211+08:00 [feishu] feishu[config]: dispatch complete (queuedFinal=true, replies=2)
2026-06-24T09:23:24.531+08:00 [feishu] feishu[config] Closed streaming

User-visible result: user only saw a ⚠️ 🛠️ card in the Feishu DM. The actual reply ("Issue #96239 created, link: ...") was the second card and was visually below the warning. We have not yet pulled the trajectory for this second run to confirm whether the same lastToolError / mutatingAction mechanism fired, or whether a different lastToolError payload was responsible. We are including this instance to demonstrate that the bug bites for short, single-shot agent replies too, not just multi-tool turns.

Gateway log excerpt (08:32 tester run)

2026-06-24T08:32:08.594+08:00 [feishu] feishu[tester]: received message from <user_id> in <chat_id> (p2p)
2026-06-24T08:32:08.631+08:00 [feishu] feishu[tester]: dispatching to agent (session=agent:tester:main)
2026-06-24T08:32:20.444+08:00 [feishu] feishu[tester] Started streaming: cardId=7654753303888907225, messageId=om_x100b6c8617f2fca0b32e362961f959a
... ~2m of exec/memory_search/gateway/process activity ...
2026-06-24T08:34:22.875+08:00 [feishu] feishu[tester]: dispatch complete (queuedFinal=true, replies=2)
2026-06-24T08:34:37.825+08:00 [feishu] feishu[tester] Closed streaming: cardId=7654753303888907225

Trajectory excerpt (08:32 tester run, 8:32:09 → 8:34:22 UTC)

trace.artifacts itemLifecycle: {startedCount: 26, completedCount: 26, activeCount: 0} — the run completed normally.

trace.artifacts toolMetas (16 entries, in order):

[0]  wiki_search: 外网调试地址 远程访问
[1]  memory_search: 外网调试地址 远程访问 URL
[2]  gateway: gateway.externalUrl
[3]  memory_search: tunnel ngrok cloudflare 外网 端口 调试
[4]  exec: print text → show ~/.openclaw/config.yaml ...
[5]  exec: run # -> show first 80 lines ...
[6]  exec: run # → print text → run ps aux -> search "grep" ...
[7]  exec: run # → print text → print text → run ps aux ...
[8]  memory_search: 外网 IP 端口转发 18765 18789 公网访问 remote
[9]  exec: # 查之前是否用过ngrok/cloudflared建隧道 ...
[10] exec: run # → show ~/.ngrok2/ngrok.yml ...
[11] exec: run # → print text
[12] exec: show ~/Library/Application Support/ngrok/ngrok.yml
[13] exec: # 启动 ngrok 隧道到 Polyphone 18765 ...
[14] process: crisp-coral
[15] exec: fetch http://localhost:18765/

trace.artifacts lastToolError: as shown above.

Expected behavior

  • A successful agent turn (finalStatus: success, all items completed) should produce exactly one user-visible reply card, not two. This applies to both multi-tool turns and short single-shot replies.
  • An exec step that only cats / reads a file and whose stdout happens to mention "configuration file" should not be classified as a mutatingAction. The agent did not modify the file.
  • If a warning is generated for any reason, it should not pre-empt the agent's actual final reply in the channel card ordering.
  • If the gateway cannot determine whether a tool call mutated state, the default should be "do not warn the user" rather than "warn the user with a visually-prior card".

Actual behavior

  • The Feishu DM shows a ⚠️ 🛠️ warning card referencing the cat ngrok.yml step (first instance) — and the user only sees a ⚠️ 🛠️ card with no obvious reason (second instance, mechanism not yet confirmed) — before the agent's actual final reply.
  • The gateway reports replies=2 for turns that, from the agent's perspective, completed exactly once.
  • In both observed instances, the user had to re-prompt the agent because they thought the reply had been lost. The re-prompt produced a second replies=2 shape, compounding the visual confusion.

Observations about the classification (first instance)

  • The string Valid configuration file at <path> in the error field matches the stdout of the previous exec step verbatim. This suggests lastToolError may be populating from a heuristic that scans exec stdout for substrings like "configuration file" rather than from a real tool error.
  • mutatingAction: true is set even though the command was a read-only cat (no write/redirect/in-place edit verb).
  • The run succeeded — itemLifecycle.activeCount: 0 and finalStatus: "success".

We have not yet identified which subsystem of the gateway sets these fields, and we are not sure if the same code path is responsible for both populating lastToolError and emitting the ⚠️ 🛠️ warning. We are filing this with whatever concrete evidence we have.

Impact

  • Data loss: None in either instance. The agent's reply is delivered, just out of order and visually buried.
  • User experience: The user has to look past the warning card to find the real reply, and may re-prompt because they think the reply was lost. In both instances we observed, the user re-prompted, which produced a follow-up turn that also suffered from the same replies=2 shape.
  • Reproducibility: We have observed this on at least two agents (tester and config) in the same Feishu DM in the same hour, with two different trigger shapes. We do not yet have a controlled reproduction script.

What we have not yet verified

  • Whether this reproduces on OpenClaw versions earlier than 2026.6.10-beta.2.
  • Whether the same lastToolError / mutatingAction behavior occurs on other channels (Discord / Telegram / WebChat).
  • Whether the second instance (09:21, config agent) was triggered by the same exec stdout heuristic or by a different code path. We have not yet pulled the trajectory for that run.
  • Whether the heuristic is specifically targeting the substring configuration file or something else about the exec metadata (run # → print text).
  • Which subsystem file/code path is responsible.

We can run additional bisects or supply more trajectory files if maintainers want to narrow this down.

Related issues (already triaged, none matched our case)

Reporter

  • OpenClaw + Feishu setup on a single Mac mini, 7 agents.
  • Trajectory files retained per session under ~/.openclaw/agents/<agent>/sessions/.
  • Gateway log at ~/Library/Logs/openclaw/gateway.log.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper-recovery-stuckclawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions