openclaw - 💡(How to fix) Fix [Bug] Feishu: p2p reactions routed to group session — chat_id oc_ prefix misidentified as group [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#59009Fetched 2026-04-08 02:30:00
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants

Root Cause

Two issues in resolveReactionSyntheticEvent (source: extensions/feishu/src/monitor.account.ts):

Fix Action

Workaround

Patch dist/monitor-D9C3Olkl.js locally — see fix suggestions above.

Code Example

const resolvedChatType = normalizeFeishuChatType(event.chat_type) ?? fallbackChatType;
if (!resolvedChatType) {
    // silently dropped — no fallback
    return null;
}

---

const syntheticChatId = syntheticChatIdRaw?.trim() ? syntheticChatIdRaw : `p2p:${senderId}`;

---

const syntheticChatId = syntheticChatIdRaw?.trim()
    ? (resolvedChatType === "p2p" || resolvedChatType === "private"
        ? `p2p:${senderId}`
        : syntheticChatIdRaw)
    : `p2p:${senderId}`;
RAW_BUFFERClick to expand / collapse

Bug Description

Feishu p2p (direct message) reaction events are incorrectly routed to a group session instead of the user's direct session, causing the agent to respond in the wrong context or not respond at all.

Root Cause

Two issues in resolveReactionSyntheticEvent (source: extensions/feishu/src/monitor.account.ts):

1. Missing chat_type fallback

Feishu's WebSocket reaction events (im.message.reaction.created_v1) do not include chat_type. When fetchMessage also returns no chatType, the event is silently dropped:

const resolvedChatType = normalizeFeishuChatType(event.chat_type) ?? fallbackChatType;
if (!resolvedChatType) {
    // silently dropped — no fallback
    return null;
}

Fix: Add a fallback (e.g., default to "p2p") since most reaction scenarios are in direct messages.

2. p2p chat_id uses oc_ prefix, misrouted as group

Feishu assigns oc_-prefixed chat_id to both group chats and p2p conversations. The synthetic event passes this raw chat_id to session routing:

const syntheticChatId = syntheticChatIdRaw?.trim() ? syntheticChatIdRaw : `p2p:${senderId}`;

When a group session exists for that oc_ chat_id, the reaction gets routed there instead of the user's direct session.

Fix: When resolvedChatType is "p2p" or "private", force syntheticChatId to p2p:${senderId} regardless of the raw chat_id:

const syntheticChatId = syntheticChatIdRaw?.trim()
    ? (resolvedChatType === "p2p" || resolvedChatType === "private"
        ? `p2p:${senderId}`
        : syntheticChatIdRaw)
    : `p2p:${senderId}`;

Steps to Reproduce

  1. Configure Feishu channel with reactionNotifications: "all" and connectionMode: "websocket"
  2. Have both a p2p (direct) session and a group session active
  3. In a p2p conversation, react to the bot's message with any emoji
  4. Observe in gateway.log:
    • Before fix: skipping reaction XXXX on om_xxx without chat type context
    • After partial fix: reaction delivered to feishu:g-oc_xxx (group session) instead of feishu:direct:ou_xxx

Expected Behavior

p2p reactions should be delivered to the user's direct session (agent:main:feishu:direct:ou_xxx).

Environment

  • OpenClaw: 2026.3.28 (also reproduced on 2026.3.31)
  • Channel: Feishu, WebSocket mode
  • Config: reactionNotifications: "all" at global and account level

Related

  • #34528 (reaction message_id suffix causes 400 — separate but co-occurring issue)
  • #33948 (add message reaction support)
  • #31652 (support reaction event notifications)

Workaround

Patch dist/monitor-D9C3Olkl.js locally — see fix suggestions above.

extent analysis

TL;DR

Update the resolveReactionSyntheticEvent function to add a fallback for missing chat_type and correctly route p2p reactions by forcing syntheticChatId to p2p:${senderId} when resolvedChatType is "p2p" or "private".

Guidance

  • Add a fallback for missing chat_type in resolveReactionSyntheticEvent to default to "p2p" when fetchMessage also returns no chatType.
  • Update the syntheticChatId assignment to force p2p:${senderId} when resolvedChatType is "p2p" or "private", regardless of the raw chat_id.
  • Verify the fix by checking the gateway.log for correct routing of p2p reactions to the user's direct session.
  • Test the fix by reproducing the steps to reproduce and observing the expected behavior.

Example

const syntheticChatId = syntheticChatIdRaw?.trim()
    ? (resolvedChatType === "p2p" || resolvedChatType === "private"
        ? `p2p:${senderId}`
        : syntheticChatIdRaw)
    : `p2p:${senderId}`;

Notes

The provided fix assumes that the senderId is available and correctly identifies the user's direct session. Additionally, this fix may not address other related issues, such as the separate issue with reaction message_id suffix causing 400 errors.

Recommendation

Apply the workaround by patching dist/monitor-D9C3Olkl.js locally with the suggested fixes, as the issue is specific to the Feishu channel and WebSocket mode.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING