Skip to content

fix(feishu): fall back to direct send when reply target is withdrawn#27614

Closed
justinhuangai wants to merge 1 commit into
openclaw:mainfrom
justinhuangai:fix/feishu-reply-withdrawn-fallback
Closed

fix(feishu): fall back to direct send when reply target is withdrawn#27614
justinhuangai wants to merge 1 commit into
openclaw:mainfrom
justinhuangai:fix/feishu-reply-withdrawn-fallback

Conversation

@justinhuangai

@justinhuangai justinhuangai commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Problem

When a Feishu user withdraws (撤回) a message while the bot is composing a reply, im.message.reply returns error 230011 or 231003. The reply is silently dropped — the user sees nothing.

This affects all message types: text, cards, images, and files.

Root Cause

All four send functions (sendMessageFeishu, sendCardFeishu, sendImageFeishu, sendFileFeishu) call im.message.reply and immediately assert success. There's no handling for the "target message gone" case:

// BEFORE — hard failure when target is withdrawn
const response = await client.im.message.reply({
  path: { message_id: replyToMessageId },
  data: { content, msg_type: msgType },
});
assertFeishuMessageApiSuccess(response, "Feishu reply failed");
// ^ throws on 230011/231003, reply is lost

Fix

Added isFeishuMessageGoneError() to detect codes 230011 (withdrawn) and 231003 (not found). When a reply target is gone, fall back to im.message.create (direct send) instead of throwing:

// AFTER — fallback to direct send
const response = await client.im.message.reply({
  path: { message_id: replyToMessageId },
  data: { content, msg_type: msgType },
});
if (isFeishuMessageGoneError(response)) {
  const fallback = await client.im.message.create({
    params: { receive_id_type: receiveIdType },
    data: { receive_id: receiveId, content, msg_type: msgType },
  });
  assertFeishuMessageApiSuccess(fallback, "Feishu send failed");
  return toFeishuSendResult(fallback, receiveId);
}
assertFeishuMessageApiSuccess(response, "Feishu reply failed");

Applied consistently across all four send functions. Non-gone errors still throw as before.

Tests

35 tests across 3 files:

  • send-result.test.tsisFeishuMessageGoneError for both codes, success, other errors, undefined
  • send.test.ts — text and card fallback (230011, 231003), non-gone error propagation, normal reply, direct send
  • media.test.ts — image and file fallback, msg_type preservation for media vs file
pnpm vitest run extensions/feishu/src/send-result.test.ts extensions/feishu/src/send.test.ts extensions/feishu/src/media.test.ts

Fixes #27103

Related #27525 (addresses typing indicator spam — a separate symptom from the same issue)

@greptile-apps

greptile-apps Bot commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Added graceful fallback when Feishu message reply targets are withdrawn or deleted (error codes 230011 and 231003). The bot now sends the reply as a new direct message instead of silently dropping it.

  • Introduced isFeishuMessageGoneError() helper to detect withdrawn (230011) or deleted (231003) target messages
  • Applied consistent fallback pattern across all four send functions: sendMessageFeishu, sendCardFeishu, sendImageFeishu, and sendFileFeishu
  • When reply fails with a "gone" error, falls back to im.message.create with the same content and msg_type
  • Comprehensive test coverage added (35 new tests) covering both error codes, non-gone errors, normal replies, and direct sends
  • All msg_type values correctly preserved in fallback (post, interactive, image, file, media)

Confidence Score: 5/5

  • This PR is safe to merge with no identified risks
  • The implementation is clean, well-tested, and follows a consistent pattern. The fallback logic is isolated to error handling paths, preserves all message content and types correctly, and is covered by comprehensive unit tests. The two error codes (230011, 231003) are specific to the withdrawn/deleted message scenario and correctly identified. No breaking changes or edge cases identified.
  • No files require special attention

Last reviewed commit: 9f3d329

@bmendonca3

Copy link
Copy Markdown
Contributor

I checked failing jobs and there is a deterministic protocol-generation blocker:

So this is currently not only a flaky Windows issue; protocol artifacts are out of sync in this branch.

Actionable fix:

  1. Run pnpm protocol:gen && pnpm protocol:gen:swift.
  2. Commit generated protocol outputs.
  3. Re-run CI.

After that, we can reassess remaining Windows-shard failures separately.

@justinhuangai
justinhuangai force-pushed the fix/feishu-reply-withdrawn-fallback branch from 9f3d329 to 5b7fe99 Compare February 26, 2026 15:41
@justinhuangai

Copy link
Copy Markdown
Contributor Author

Thanks for catching that! Rebased onto latest main (5b7fe99) — the protocol drift was from upstream #27589 (deviceFamily field) landing after my last push. CI should be green now.

@justinhuangai
justinhuangai force-pushed the fix/feishu-reply-withdrawn-fallback branch 5 times, most recently from a366877 to 1d291a5 Compare February 26, 2026 17:32
When a user withdraws or deletes a message after the bot has started
composing a reply, the Feishu API returns error 230011 (withdrawn) or
231003 (not found). Previously this caused a hard failure that dropped
the reply entirely.

Add `isFeishuMessageGoneError()` helper to detect these codes and apply
a fallback-to-direct-send pattern in all four reply paths:
`sendMessageFeishu`, `sendCardFeishu`, `sendImageFeishu`, and
`sendFileFeishu`.

Closes openclaw#27103

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@justinhuangai
justinhuangai force-pushed the fix/feishu-reply-withdrawn-fallback branch from 1d291a5 to f5477c7 Compare February 27, 2026 03:19
@justinhuangai

Copy link
Copy Markdown
Contributor Author

Closing — the reply fallback for withdrawn/deleted messages was implemented upstream in 2a252a1 (fix(feishu): harden target routing, dedupe, and reply fallback). Upstream now handles error codes 230011/231003 with the same fallback-to-direct-send pattern. Great to see this fixed! Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: feishu Channel integration: feishu size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feishu: reply silently dropped when target message is withdrawn/deleted

2 participants