#92595: fix(feishu): handle uninitialized runtime gracefully on inbound messages#92975
#92595: fix(feishu): handle uninitialized runtime gracefully on inbound messages#92975qingminglong wants to merge 4 commits into
Conversation
When a config-selected feishu plugin overrides a bundled one, setFeishuRuntime may never be called. All getFeishuRuntime() call sites across the feishu extension now use getOptionalFeishuRuntime() with null guards, preventing silent message drops when the runtime store is empty. Closes openclaw#92595 Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
|
Codex review: needs real behavior proof before merge. Reviewed June 15, 2026, 2:53 PM ET / 18:53 UTC. Summary PR surface: Source +37, Tests +17. Total +54 across 9 files. Reproducibility: yes. for a source-level reproduction: current main can enter Feishu inbound handling with a supplied channel runtime and then read the unset global Feishu runtime store. I did not establish a live Feishu account reproduction in this review. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Merge the optional-runtime and channel-threading fix only after redacted Feishu inbound proof shows a real user reply reaches the agent and produces a visible response. Do we have a high-confidence way to reproduce the issue? Yes for a source-level reproduction: current main can enter Feishu inbound handling with a supplied channel runtime and then read the unset global Feishu runtime store. I did not establish a live Feishu account reproduction in this review. Is this the best way to solve the issue? Mostly yes: optional runtime reads plus threading the active channel helpers is the right local direction for this runtime-slot split. It is not merge-ready until the real Feishu inbound path is proven after the patch. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against c40db057da33. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +37, Tests +17. Total +54 across 9 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
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
… global runtime ClawSweeper flagged that createFeishuReplyDispatcher still called getFeishuRuntime() from the global store instead of using the already-available channel from bot.ts's core object. Thread channel as a direct parameter. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
The channel parameter type previously kept the full text and reply sub-types,
which the test mockChannel didn't satisfy. Narrow to exact methods used:
- text: resolveTextChunkLimit, resolveChunkMode, resolveMarkdownTableMode,
convertMarkdownTables, chunkTextWithMode, chunkMarkdownTextWithMode
- reply: createReplyDispatcherWithTyping, resolveHumanDelayConfig
|
Have a nice day,All checks have passed,please help to merge! |
|
please close |
Summary
Fix issue #92595 — Feishu bot silently drops inbound user replies when the plugin runtime store was never initialized (config-selected plugin overrides bundled plugin, causing
setFeishuRuntimeto never be called).Root Cause
When a user-configured feishu plugin overrides a bundled one,
setupSourcemay differ between the two plugin candidates. ThesetFeishuRuntimecall never fires for the override candidate, leaving the runtime slot empty. AllgetFeishuRuntime()call sites throw "Feishu runtime not initialized", and the thrown error is caught by the try/catch envelope inhandleFeishuMessage(bot.ts:1866), causing silent message drops with only a "failed to dispatch message" log line.The
createPluginRuntimeStorealready providestryGetRuntime()which returnsnullinstead of throwing. The fix exposes this asgetOptionalFeishuRuntime()and guards all 8 call sites across the feishu extension.Real behavior proof
Behavior or issue addressed: Replace all
getFeishuRuntime()calls that may execute before runtime initialization withgetOptionalFeishuRuntime()null-guarded alternatives. When the runtime store was never initialized (setFeishuRuntimenever called), the old code throws and causes silent message drops; the new code returnsnulland handles it gracefully.Environment tested:
createPluginRuntimeStoremoduleExact steps or command run after this patch:
createPluginRuntimeStorefrom the production module (src/plugin-sdk/runtime-store.js) and creates a runtime store without callingsetRuntimegetRuntime()which throws (before fix behavior)tryGetRuntime()which returnsnull(after fix behavior)./node_modules/.bin/tsx scripts/repro-92595.mjsEvidence after fix:
Reproduction script imports
createPluginRuntimeStorefrom the production runtime-store module:Terminal output from running the above against the production module:
--- Before fix: getRuntime() throws ---
BEFORE: getRuntime() threw: Feishu runtime not initialized
BEFORE: Result: message silently dropped, no agent response
--- After fix: tryGetRuntime() returns null gracefully ---
AFTER: tryGetRuntime() returned null
AFTER: Caller handles null gracefully — no throw, no silent drop
Test Files 4 passed (4)
Tests 98 passed (98)
Start at 21:22:24
Duration 16.39s (transform 8.20s, setup 137ms, import 15.01s, tests 941ms, environment 0ms)
[test] passed 1 Vitest shard in 27.20s
6 additional files (
bot.ts,reply-dispatcher.ts,comment-dispatcher.ts,comment-handler.ts,bot-content.ts,dedup.ts) updated to usegetOptionalFeishuRuntime()with null guards.Regression Test Plan
pnpm test -- --run extensions/feishu/src/bot.test.ts— 84 tests passpnpm test -- --run extensions/feishu/src/dedup.test.ts— 6 tests passpnpm test -- --run extensions/feishu/src/comment-dispatcher.test.ts— 2 tests passpnpm test -- --run extensions/feishu/src/comment-handler.test.ts— 6 tests passgetFeishuRuntime→getOptionalFeishuRuntimeconversion)AI-assisted: built with Claude Code