Skip to content

fix(feishu): route markdown tables through post instead of broken interactive card - #45583

Closed
Zjrua wants to merge 1 commit into
NousResearch:mainfrom
Zjrua:fix/feishu-table-post-routing
Closed

fix(feishu): route markdown tables through post instead of broken interactive card#45583
Zjrua wants to merge 1 commit into
NousResearch:mainfrom
Zjrua:fix/feishu-table-post-routing

Conversation

@Zjrua

@Zjrua Zjrua commented Jun 13, 2026

Copy link
Copy Markdown

Bug

Markdown tables in Feishu messages render as blank/empty content. The gateway logs show:

[230099] Failed to create card content, ext=ErrCode: 200914; ErrMsg: table rows is invalid; ErrorValue: row idx:1;

Root cause

_build_outbound_payload() routes any content containing a markdown table to the interactive card path (msg_type=interactive), which builds a card table element via _parse_markdown_table_to_card_element().

The generated table JSON format is invalid per Feishu's card table API spec:

  • Missing required page_size field
  • Missing header_row
  • Missing data_type and display_name in column definitions
  • Cells use bare {"tag": "plain_text", "content": ...} instead of {"text": {"tag": "plain_text", ...}}

This causes the Feishu API to reject the card with error 230099, resulting in blank messages.

Additionally, during streaming, the initial chunk is sent as post/text and then the final edit tries to switch to interactive — Feishu does not allow changing msg_type on message update, causing further failures.

Fix

Route markdown tables through the post type (same as other markdown content) instead of the interactive card. Markdown tables in post md elements render correctly on Feishu clients.

# Before (broken):
if _MARKDOWN_TABLE_RE.search(content):
    return "interactive", self._build_table_card_payload(content)

# After (fixed):
if _MARKDOWN_HINT_RE.search(content) or _MARKDOWN_TABLE_RE.search(content):
    return "post", _build_markdown_post_payload(content)

Testing

Verified on Feishu (websocket mode) with various markdown tables — all render correctly via post type. The interactive card approach produced blank messages consistently.

…n interactive card

Markdown tables in Feishu post 'md' elements render correctly, but the
interactive card table element format was invalid (missing required
page_size, header_row, display_name fields), causing Feishu API error
230099 (ErrCode 200914: table rows is invalid) and blank messages.

The card table approach also fails during streaming edits because Feishu
does not allow changing msg_type (post → interactive) on message update.

Routing tables through post alongside other markdown content is simpler
and renders correctly on all Feishu clients.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery platform/feishu Feishu / Lark adapter labels Jun 13, 2026
@Zjrua

Zjrua commented Jun 13, 2026

Copy link
Copy Markdown
Author

Related issues & PRs

Search found several existing issues/PRs addressing the same Feishu markdown table problem:

Bug reports:

Similar approaches (post routing):

Card-based attempts (same root cause — invalid card table format):

All card-based PRs appear stuck — the Feishu card table JSON format has strict requirements (page_size, header_row, data_type, display_name, cell {"text": {...}} wrapper) that are easy to get wrong. This PR takes the simpler post routing approach that works reliably today.

Closes #9549

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

Feishu markdown tables now route through a native card table element instead of falling back to plain text, which was causing tables to appear blank. The fix parses markdown tables into Feishu card element format, with non-table content continuing through the standard post/markdown path. Also fixes a text-edit fallback that falls back to post if the initial edit failed due to msg_type mismatch. Well-scoped fix with good test coverage.


Reviewed by Hermes Agent

@laradocs

Copy link
Copy Markdown

Alternative approach: Schema 2.0 card with {"tag": "markdown"} instead of post fallback

Instead of routing tables back to post/md, consider the approach taken by #45420: detect markdown content with headings/tables/blockquotes and auto-wrap it into a Schema 2.0 interactive card with a {"tag": "markdown"} body element. This is the recommended approach per Lark/Feishu docs — Schema 2.0 markdown elements handle tables, headings, blockquotes, and all standard CommonMark syntax natively, while post/md silently drops headings and blockquotes on some clients.

The key difference: instead of parsing the markdown table into a card table element (which is complex and error-prone as seen with error 230099), wrap the entire markdown content as a single {"tag": "markdown", "content": content} element. This is simpler, avoids the Schema 1.0 table element pitfalls, and also fixes headings/blockquotes rendering which post/md doesn't handle reliably.

Relevant docs:

@Zjrua

Zjrua commented Jun 27, 2026

Copy link
Copy Markdown
Author

Superseded by #53453 — cleaner diff (no dead CardKit code), targets the correct post-migration file path, and additionally fixes the streaming edit fallback edge case.

@Zjrua Zjrua closed this Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have platform/feishu Feishu / Lark adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants