#15564: fix: webchat messages disappear during concurrent session activity
app: web-ui
gateway
stale
size: S
## Summary
- **CIDR support for `gateway.trustedProxies`**: `isTrustedProxyAddress` did exact string matching, so CIDR entries like `100.64.0.0/10` never matched real IPs. Connections through a reverse proxy triggered "Proxy headers detected from untrusted address" warnings and unnecessary WebSocket reconnects that cleared chat state.
- **Optimistic message persistence in webchat UI**: When a user sends a webchat message, the UI adds it to `chatMessages` optimistically. If another run on the same session completes (Telegram, cron) or the WebSocket reconnects, `loadChatHistory` replaces all in-memory messages with server data that doesn't yet include the pending message — making it vanish. Fix tracks the optimistic message in a module-level variable and re-appends it after server refreshes until the server history catches up.
## Test plan
- [ ] Send a webchat message while a Telegram message is being processed on the same agent session — user message should remain visible
- [ ] Trigger a WebSocket reconnect (e.g. restart gateway) while a webchat message is pending — message should reappear after reconnect
- [ ] Configure `trustedProxies` with a CIDR range (e.g. `127.0.0.0/8`) and connect through a reverse proxy — no "untrusted proxy" warning
- [ ] Verify exact-IP entries in `trustedProxies` still work (backwards compatible)
- [ ] Verify optimistic message clears after agent responds (final event)
🤖 Generated with [Claude Code](https://claude.com/claude-code) — AI-assisted, tested on a live OpenClaw gateway instance
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR addresses two sources of “disappearing webchat messages”:
- **Gateway**: `isTrustedProxyAddress` now supports CIDR entries in `gateway.trustedProxies`, so reverse proxies configured with ranges (e.g. `100.64.0.0/10`) can be recognized and won’t trigger the “untrusted proxy headers” path that leads to reconnect churn.
- **Control UI / webchat**: `loadChatHistory` preserves a single optimistic user message across history refreshes/reconnects by re-appending it until server history appears to include a user message at/after the optimistic timestamp.
<h3>Confidence Score: 3/5</h3>
- Moderate confidence; one user-visible edge case should be fixed before merge.
- Core changes are small and locally-scoped, but the optimistic-message persistence adds a new global pending state that is not cleared on send failures, which can leave stuck/duplicate UI messages after a refresh/reconnect.
- ui/src/ui/controllers/chat.ts
<sub>Last reviewed commit: edc4fe9</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#14309: fix(ui): resolve chat event session key mismatch
by justonlyforyou · 2026-02-11
83.8%
#9218: Fix Control UI chat resync on gaps and terminal events
by figitaki · 2026-02-05
81.9%
#14966: fix(webchat): preserve user message visibility after chat.send
by BenediktSchackenberg · 2026-02-12
81.4%
#3721: fix(ui): webchat not displaying chat responses
by maxmaxrouge-rgb · 2026-01-29
80.9%
#8742: fix(webchat): hide internal system messages from UI (#7440)
by revenuestack · 2026-02-04
80.9%
#11123: Fix webchat→external channel cross-delivery
by jingkang0822 · 2026-02-07
79.7%
#16767: fix: auto-resync webchat on reconnect and prevent message flicker o...
by alewcock · 2026-02-15
79.6%
#13902: fix: auto-recover on event gap instead of showing error
by nikogamulin · 2026-02-11
79.2%
#7127: fix(webchat): add regenerate flag to prevent context leak on response…
by craihub · 2026-02-02
78.8%
#3182: fix(gateway): use canonical session key in chat.send
by chrisherold · 2026-01-28
78.0%