fix(mattermost): add timeout to REST client requests#102027
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 9, 2026, 7:07 AM ET / 11:07 UTC. Summary PR surface: Source +47, Tests +123. Total +170 across 3 files. Reproducibility: yes. from source and PR proof. Current main's Mattermost client does not pass a timeout into fetchWithSsrFGuard, and the PR demonstrates the accepted-but-never-responding request shape with a real local HTTP server; I did not run tests in this read-only review. Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land the bounded Mattermost client timeout after maintainers accept the 30-second all-REST default, or add a documented longer per-surface deadline for any proven long-running Mattermost operation before merge. Do we have a high-confidence way to reproduce the issue? Yes from source and PR proof. Current main's Mattermost client does not pass a timeout into fetchWithSsrFGuard, and the PR demonstrates the accepted-but-never-responding request shape with a real local HTTP server; I did not run tests in this read-only review. Is this the best way to solve the issue? Yes, with upgrade-risk acceptance. Using the existing SSRF guard timeout and shared AbortSignal helper inside the Mattermost client is the narrow maintainable fix; a longer per-surface exception is safer only if maintainers expect uploads or self-hosted calls to exceed 30 seconds. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 56096eb8590c. Label changesLabel justifications:
Evidence reviewedPR surface: Source +47, Tests +123. Total +170 across 3 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (8 earlier review cycles)
|
|
Merged current upstream/main to refresh the stale failed CI run. The Mattermost change remains limited to the REST client timeout path, including the existing DM retry preservation. Local validation on the new head:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
5c224c4 to
fb13567
Compare
fb13567 to
fe84027
Compare
|
Maintainer review/proof complete.
Known proof gap: no live Mattermost deployment was available. The loopback transport proof covers default timeout, caller abort, and longer per-request retry override behavior. |
|
Merged via squash.
|
Prevent Tlon REST client requests from hanging when the server accepts a request but never responds. Add a default 30s timeout to all fetchWithSsrFGuard calls in tlon-api.ts, following the same pattern as PR openclaw#102027 (Mattermost timeout fix). Changes: - Add TLON_API_REQUEST_TIMEOUT_MS constant (30 seconds) - Pass timeoutMs to getMemexUploadUrl fetchWithSsrFGuard call - Pass timeoutMs to Memex upload fetchWithSsrFGuard call - Pass timeoutMs to custom S3 upload fetchWithSsrFGuard call This ensures bounded failures instead of stuck upload requests when self-hosted or remote servers stall after accepting connections.
* fix(mattermost): add timeout to REST client requests * fixup: preserve Mattermost DM retry timeout * test(mattermost): reuse hanging server helper * test(mattermost): satisfy timeout lint --------- Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
Fixes an issue where Mattermost message delivery and lookup workflows could hang when the Mattermost REST API accepts a request but never sends a response.
Why This Change Was Made
The shared Mattermost REST client now applies a 30s default request timeout while preserving SSRF/private-network policy and caller abort signals. Per-request
timeoutMsremains supported so existing Mattermost DM retry attempts can keep their longer retry deadline instead of being preempted by the client default.User Impact
Users and operators get a bounded Mattermost REST failure instead of a stuck send, reaction, upload, or target-resolution request when a self-hosted or remote server stalls after accepting the connection.
Evidence
TMPDIR=/media/vdc/0668001470/tmp/openclaw-task-tmp node scripts/run-vitest.mjs extensions/mattermost/src/mattermost/client.fetch-timeout.test.ts extensions/mattermost/src/mattermost/client.retry.test.ts extensions/mattermost/src/mattermost/send.test.ts- passed;Test Files 3 passed (3),Tests 59 passed (59).cbx_720f70198a7e, runrun_7a0bad083ef5, passed the timeout, retry, and client suites atfe84027dc79865a3d98291b3b71782cd875a9829(3 files, 53 tests).TMPDIR=/media/vdc/0668001470/tmp/openclaw-task-tmp node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.extensions.json extensions/mattermost/src/mattermost/client.ts extensions/mattermost/src/mattermost/client.fetch-timeout.test.ts extensions/mattermost/src/mattermost/client.retry.test.ts extensions/mattermost/src/mattermost/send.ts extensions/mattermost/src/mattermost/send.test.ts- passed; exit 0.git diff --check- passed; exit 0.timeoutMsline made the focused Vitest fail withExpected: "rejected"andReceived: "pending"; restoring the patch returned the test to green.Real behavior proof
Behavior addressed: Mattermost REST client requests now have a deadline when the server accepts the request but never responds, without shortening the existing DM retry timeout path.
Real environment tested: local Linux Node source checkout; real
node:httploopback server that accepts the connection and never responds, driving the real exportedcreateMattermostClient,fetchMattermostMe, andcreateMattermostDirectChannelWithRetrypaths.Exact steps or command run after this patch:
TMPDIR=/media/vdc/0668001470/tmp/openclaw-task-tmp node scripts/run-vitest.mjs extensions/mattermost/src/mattermost/client.fetch-timeout.test.ts extensions/mattermost/src/mattermost/client.retry.test.ts extensions/mattermost/src/mattermost/send.test.tsEvidence after fix: the focused timeout test asserts the loopback server receives
/api/v4/users/me; without timeout wiring the request stays pending past the race window, and withtimeoutMs: 50it rejects with an abort/timeout-class error. A caller-signal test proves caller aborts are still honored. A DM retry compatibility test configures a 50ms client default and a 250ms direct-channel retry timeout, observes the request still pending at 120ms, then observes timeout-class rejection by 600ms.Observed result after fix:
Test Files 3 passed (3)andTests 59 passed (59).What was not tested: a live Mattermost deployment; the hang is reproduced with a real local HTTP server, not the real third-party service.