Skip to content

fix(msteams): channel file attachments broken by overly-broad HTML fallback (#58617, #51749)#64645

Merged
BradGroux merged 2 commits intoopenclaw:mainfrom
sudie-codes:fix/msteams-channel-attachments-58617
Apr 12, 2026
Merged

fix(msteams): channel file attachments broken by overly-broad HTML fallback (#58617, #51749)#64645
BradGroux merged 2 commits intoopenclaw:mainfrom
sudie-codes:fix/msteams-channel-attachments-58617

Conversation

@sudie-codes
Copy link
Copy Markdown
Contributor

Summary

Channel file attachments (users uploading files into a Teams channel conversation) were silently failing because the Graph media fallback was triggering on any HTML attachment — including @mention cards — and calling a nonexistent Graph sub-resource.

Root cause

  1. hasHtmlAttachment in inbound-media.ts treated all text/html attachments as file candidates, including mention cards
  2. Graph fallback path called \${messageUrl}/attachments — a sub-resource that does not exist in the Graph API
  3. Errors were swallowed by empty catch {} blocks, masking the real failure

Fix

  • Gate fallback on presence of <attachment id="..."> tags in the HTML content
  • Source attachments from the chatMessage.attachments array returned by the main message fetch (correct Graph path)
  • Replace empty catch {} with proper error logging

Fixes #58617
Fixes #51749

Test plan

  • @mention cards no longer trigger fallback
  • Real file attachments route through the correct Graph path
  • Errors are now logged instead of swallowed
  • Manual: upload a file to a Teams channel with the bot

🤖 Generated with Claude Code

@openclaw-barnacle openclaw-barnacle Bot added channel: msteams Channel integration: msteams size: M labels Apr 11, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 11, 2026

Greptile Summary

This PR fixes two related bugs in the MS Teams channel media pipeline: (1) the hasHtmlAttachment gate in inbound-media.ts fired on any text/html attachment (including @mention cards), triggering spurious Graph/Bot Framework fallback calls; and (2) the Graph fallback incorrectly called a nonexistent ${messageUrl}/attachments sub-resource instead of reading the inline attachments array returned by the main message fetch. Empty catch {} blocks that previously hid both failures are replaced with structured log.debug calls. The fix is correctly scoped, well-tested, and does not introduce regressions.

Confidence Score: 5/5

Safe to merge — all three root causes are correctly addressed, the fix is well-scoped, and test coverage directly validates the regressions.

No P0 or P1 findings. The attachment sourcing change (inline array vs. nonexistent sub-resource), the fallback gate (attachment IDs vs. content-type), and the error-logging improvements are all logically sound. The attachmentCount computation is verified to equal the total message attachment count regardless of SharePoint success/failure splits. Test coverage is thorough for all changed paths.

No files require special attention.

Reviews (1): Last reviewed commit: "fix(msteams): gate channel attachment fa..." | Re-trigger Greptile

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aef95e98dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +65 to +66
const attachmentIds = extractMSTeamsHtmlAttachmentIds(attachments);
const hasHtmlFileAttachment = attachmentIds.length > 0;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Trigger Graph fallback for hosted-content HTML images

This change gates both Bot Framework and Graph fallback on attachmentIds.length > 0, so HTML messages without <attachment id="..."> now skip downloadMSTeamsGraphMedia entirely. That drops valid media cases where Teams only provides inline/hosted image markup (for example cid: or hosted-content <img> sources): downloadMSTeamsAttachments does not fetch cid: sources, so mediaList stays empty and the only remaining path that can fetch /hostedContents is bypassed. As a result, inline image attachments that previously resolved through Graph hosted content will be silently lost.

Useful? React with 👍 / 👎.

@BradGroux BradGroux force-pushed the fix/msteams-channel-attachments-58617 branch from 047a8cb to 8aca740 Compare April 11, 2026 13:13
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8aca740277

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// too, so keying off contentType alone produces spurious 404 diagnostics
// for every mention-only message and masks real file attachments (#58617).
const attachmentIds = extractMSTeamsHtmlAttachmentIds(attachments);
const hasHtmlFileAttachment = attachmentIds.length > 0;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep Graph fallback for hosted-content HTML images

Gating both fallback paths on attachmentIds.length > 0 means HTML messages without <attachment id="..."> never reach downloadMSTeamsGraphMedia, even when they still contain media that only Graph can resolve (for example cid:/hosted-content images). In this code path, downloadMSTeamsAttachments cannot recover those sources because inline extraction skips cid: URLs, so inbound images are silently dropped whenever Teams sends mention-free hosted HTML without attachment tags.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle Bot added commands Command implementations scripts Repository scripts labels Apr 11, 2026
@BradGroux BradGroux force-pushed the fix/msteams-channel-attachments-58617 branch from 093a12c to 8c86959 Compare April 11, 2026 18:01
@openclaw-barnacle openclaw-barnacle Bot removed scripts Repository scripts commands Command implementations labels Apr 11, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8c869595e1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// too, so keying off contentType alone produces spurious 404 diagnostics
// for every mention-only message and masks real file attachments (#58617).
const attachmentIds = extractMSTeamsHtmlAttachmentIds(attachments);
const hasHtmlFileAttachment = attachmentIds.length > 0;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep Graph fallback for HTML media without attachment IDs

Conditioning fallback on attachmentIds.length > 0 causes non-Bot-Framework messages with HTML media but no <attachment id="..."> tags to skip downloadMSTeamsGraphMedia, which drops valid inbound images that are only retrievable through Graph hosted content. Fresh evidence: extractInlineImageCandidates in extensions/msteams/src/attachments/shared.ts explicitly skips cid: sources, so the direct attachment downloader cannot recover those images after this gate short-circuits.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle Bot added the agents Agent runtime and tooling label Apr 11, 2026
@BradGroux BradGroux force-pushed the fix/msteams-channel-attachments-58617 branch from 885e5b9 to 1ed0358 Compare April 12, 2026 00:48
@openclaw-barnacle openclaw-barnacle Bot removed the agents Agent runtime and tooling label Apr 12, 2026
@BradGroux BradGroux force-pushed the fix/msteams-channel-attachments-58617 branch from 1ed0358 to bd84012 Compare April 12, 2026 04:32
@BradGroux BradGroux merged commit 2c211d1 into openclaw:main Apr 12, 2026
9 checks passed
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bd84012b0f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +82 to +86
const bfMedia = await downloadMSTeamsBotFrameworkAttachments({
serviceUrl,
attachmentIds,
tokenProvider,
maxBytes,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Forward logger to Bot Framework attachment downloader

Pass log through when calling downloadMSTeamsBotFrameworkAttachments; this call used to provide logger but now omits it, so failures inside the downloader (token acquisition errors, non-OK attachment info/view fetches, parse/read failures) no longer emit the warning diagnostics in attachments/bot-framework.ts. In personal-chat file upload scenarios this turns real download errors into a generic bot framework attachments fetch empty debug line, which regresses observability for the exact failure mode this change set is trying to make diagnosable.

Useful? React with 👍 / 👎.

trudbot pushed a commit to trudbot/openclaw that referenced this pull request Apr 12, 2026
…llback (openclaw#58617, openclaw#51749) (openclaw#64645)

* fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749)

* test(msteams): remove dead mock branch in graph.test.ts
TOMUIV pushed a commit to TOMUIV/openclaw that referenced this pull request Apr 14, 2026
…llback (openclaw#58617, openclaw#51749) (openclaw#64645)

* fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749)

* test(msteams): remove dead mock branch in graph.test.ts
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…llback (openclaw#58617, openclaw#51749) (openclaw#64645)

* fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749)

* test(msteams): remove dead mock branch in graph.test.ts
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…llback (openclaw#58617, openclaw#51749) (openclaw#64645)

* fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749)

* test(msteams): remove dead mock branch in graph.test.ts
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…llback (openclaw#58617, openclaw#51749) (openclaw#64645)

* fix(msteams): gate channel attachment fallback on <attachment> tags (openclaw#58617, openclaw#51749)

* test(msteams): remove dead mock branch in graph.test.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: msteams Channel integration: msteams size: M

Projects

None yet

2 participants