openclaw - ✅(Solved) Fix [Bug]: msteams channel file attachments not downloaded — Graph fallback triggers on non-file HTML attachments [1 pull requests, 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#58617Fetched 2026-04-08 02:00:09
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
cross-referenced ×2

When users attach files (PDFs, images, etc.) to Teams channel messages, the bot cannot see or access the file content. The LLM only receives the text portion of the message.

Additionally, the Graph API media fallback path fires excessively for non-file messages (any message with @mentions), generating misleading [DEBUG-MEDIA] graph media fetch empty error logs.

Error Message

Additionally, the Graph API media fallback path fires excessively for non-file messages (any message with @mentions), generating misleading [DEBUG-MEDIA] graph media fetch empty error logs. Teams delivers @mention formatting as text/html Bot Framework attachments. So every @BotName message triggers the Graph API media fallback, even when there's no file. This produces noisy [DEBUG-MEDIA] graph media fetch empty error-level logs with attachmentStatus: 404 (the /attachments sub-resource doesn't exist in Graph API v1.0 for channel messages).

Root Cause

Two related problems:

1. Graph fallback triggers on @mention HTML cards (false positive)

The fallback condition in resolveMSTeamsInboundMedia() is:

if (attachments.length > 0 && attachments.every(att => 
    String(att.contentType ?? "").startsWith("text/html")))

Teams delivers @mention formatting as text/html Bot Framework attachments. So every @BotName message triggers the Graph API media fallback, even when there's no file. This produces noisy [DEBUG-MEDIA] graph media fetch empty error-level logs with attachmentStatus: 404 (the /attachments sub-resource doesn't exist in Graph API v1.0 for channel messages).

2. Actual file uploads may not be processed correctly

For channel file uploads, Teams stores the file in SharePoint and the Graph API message includes a contentType: "reference" attachment with a SharePoint contentUrl. The plugin code handles this path:

  1. Fetches message body via Graph → finds reference attachments → downloads via /shares/u!{base64url}/driveItem/content

However, in practice:

  • The Bot Framework activity for channel file uploads delivers the file info as text/html cards, not as application/vnd.microsoft.teams.file.download.info attachments (which is the DM format)
  • The Graph fallback should find the reference attachment in the message body, but it's unclear if the activity.id used to construct the Graph URL always matches the Graph message ID
  • Some Graph fetches return hostedStatus: 404 for the first candidate URL, suggesting activity ID → Graph message ID mismatch

Fix Action

Fixed

PR fix notes

PR #58632: fix(msteams): tighten html attachment fallback

Description (problem / solution / changelog)

Summary

  • Problem: Teams mention-only text/html attachments still triggered Graph media fallback, and the Graph media path still attempted ${messageUrl}/attachments instead of using the message body's attachments array.
  • Why it matters: mention-only messages generated noisy fallback attempts and misleading empty-fetch diagnostics, while legitimate Graph attachment handling depended on a redundant and undocumented fetch path.
  • What changed: gate the Graph fallback on real <attachment> tags in HTML attachments, reuse chatMessage.attachments from the fetched message body, and add regression tests for both behaviors.
  • What did NOT change (scope boundary): this PR does not change message ID candidate selection or broader Teams file-download auth behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #58617
  • Related #58617
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

  • Root cause: resolveMSTeamsInboundMedia() treated any all-text/html attachment set as a Graph-media fallback candidate, even though Teams mention markup also arrives as text/html and does not imply a downloadable file.
  • Missing detection / guardrail: there was no regression test ensuring mention-only HTML skips Graph fallback, and no test asserting Graph media reuses chatMessage.attachments from the message resource.
  • Prior context (git blame, prior PR, issue, or refactor if known): issue #58617 documents the observed behavior; I did not trace a single introducing PR with confidence.
  • Why this regressed now: Teams channel mentions and file-card markup share the same text/html transport shape, so the broader fallback condition matched both.
  • If unknown, what was ruled out: this PR does not assume a universal message-id mismatch because the current code already tries several message-id candidates.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/msteams/src/monitor-handler/inbound-media.test.ts, extensions/msteams/src/attachments.test.ts
  • Scenario the test should lock in: mention-only HTML attachments must not trigger Graph fallback, and Graph media downloads must source attachments from the fetched message body rather than ${messageUrl}/attachments.
  • Why this is the smallest reliable guardrail: both decisions are local branching rules with stable inputs and do not need a full Teams roundtrip to validate.
  • Existing test that already covers this (if any): existing attachment tests covered SharePoint reference downloads but not the fallback trigger condition or the redundant /attachments fetch.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • Teams mention-only channel messages stop triggering empty Graph media fallback attempts.
  • Teams Graph media downloads now rely on the message body's attachment data instead of a redundant follow-up fetch.

Diagram (if applicable)

Before:
mention-only html -> onlyHtmlAttachments=true -> Graph fallback -> empty fetch noise
file html -> onlyHtmlAttachments=true -> Graph fallback -> attachment handling

After:
mention-only html -> attachmentTags=0 -> no Graph fallback
file html with <attachment> -> attachmentTags>0 -> Graph fallback -> attachment handling

Security Impact (required)

  • New permissions/capabilities? (Yes/No): No
  • Secrets/tokens handling changed? (Yes/No): No
  • New/changed network calls? (Yes/No): No
  • Command/tool execution surface changed? (Yes/No): No
  • Data access scope changed? (Yes/No): No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS 15.3 / darwin 25.3.0
  • Runtime/container: Node 22+ via repo scripts
  • Model/provider: N/A
  • Integration/channel (if any): msteams
  • Relevant config (redacted): default test config

Steps

  1. Send a Teams channel message that contains only mention HTML attachments.
  2. Observe the inbound media resolution path.
  3. Send a Teams channel file message that resolves through Graph message attachments.

Expected

  • Mention-only HTML does not trigger Graph media fallback.
  • Graph file handling uses the fetched message body's attachments array.

Actual

  • Before this change, mention-only HTML could enter Graph fallback.
  • Before this change, Graph media also tried ${messageUrl}/attachments.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: ran pnpm test:extension msteams successfully; verified the new unit coverage for mention-only HTML and the updated Graph attachment path; ran pnpm build successfully.
  • Edge cases checked: mention-only HTML skips fallback, HTML with <attachment> tags still falls back, SharePoint reference attachments still merge with hosted content without calling ${messageUrl}/attachments.
  • What you did not verify: live Teams channel traffic against a real tenant.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No): Yes
  • Config/env changes? (Yes/No): No
  • Migration needed? (Yes/No): No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: Teams file-card HTML without <attachment> tags would no longer trigger Graph fallback.
    • Mitigation: the fallback now keys off the explicit attachment markup Teams uses for file cards, and the direct attachment downloader remains unchanged for normal attachment payloads.
  • Risk: repo-wide pnpm check is currently blocked by unrelated existing tsgo failures in extensions/diffs/src/language-hints.test.ts.
    • Mitigation: this PR still includes a green pnpm test:extension msteams lane and a green pnpm build run for the touched surface.

AI Assistance

  • AI-assisted
  • Testing: lightly tested on the touched surface (pnpm test:extension msteams, pnpm build; pnpm check blocked by unrelated existing tsgo failures in extensions/diffs/src/language-hints.test.ts)
  • Prompts/session logs: available on request
  • Confirmed understanding: yes

Made with Cursor

Changed files

  • extensions/msteams/src/attachments.test.ts (modified, +4/-12)
  • extensions/msteams/src/attachments/graph.ts (modified, +7/-10)
  • extensions/msteams/src/monitor-handler/inbound-media.test.ts (added, +147/-0)
  • extensions/msteams/src/monitor-handler/inbound-media.ts (modified, +10/-6)

Code Example

if (attachments.length > 0 && attachments.every(att => 
    String(att.contentType ?? "").startsWith("text/html")))
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Summary

When users attach files (PDFs, images, etc.) to Teams channel messages, the bot cannot see or access the file content. The LLM only receives the text portion of the message.

Additionally, the Graph API media fallback path fires excessively for non-file messages (any message with @mentions), generating misleading [DEBUG-MEDIA] graph media fetch empty error logs.

Version

  • OpenClaw: 2026.3.24 (also checked 2026.3.31 — same behavior)
  • Channel: msteams (bundled plugin)

Analysis

Two related problems:

1. Graph fallback triggers on @mention HTML cards (false positive)

The fallback condition in resolveMSTeamsInboundMedia() is:

if (attachments.length > 0 && attachments.every(att => 
    String(att.contentType ?? "").startsWith("text/html")))

Teams delivers @mention formatting as text/html Bot Framework attachments. So every @BotName message triggers the Graph API media fallback, even when there's no file. This produces noisy [DEBUG-MEDIA] graph media fetch empty error-level logs with attachmentStatus: 404 (the /attachments sub-resource doesn't exist in Graph API v1.0 for channel messages).

2. Actual file uploads may not be processed correctly

For channel file uploads, Teams stores the file in SharePoint and the Graph API message includes a contentType: "reference" attachment with a SharePoint contentUrl. The plugin code handles this path:

  1. Fetches message body via Graph → finds reference attachments → downloads via /shares/u!{base64url}/driveItem/content

However, in practice:

  • The Bot Framework activity for channel file uploads delivers the file info as text/html cards, not as application/vnd.microsoft.teams.file.download.info attachments (which is the DM format)
  • The Graph fallback should find the reference attachment in the message body, but it's unclear if the activity.id used to construct the Graph URL always matches the Graph message ID
  • Some Graph fetches return hostedStatus: 404 for the first candidate URL, suggesting activity ID → Graph message ID mismatch

Expected Behavior

  1. File attachments uploaded in Teams channels should be downloaded and included in the LLM context
  2. The Graph fallback should NOT trigger for messages that only have @mention HTML cards (no actual file content)
  3. The ${messageUrl}/attachments endpoint (which returns 404 since it doesn't exist in Graph v1.0) should not be called — file attachments are in the message body's attachments array, not a sub-resource

Steps to Reproduce

  1. Configure the msteams channel plugin with appropriate Graph API permissions (ChannelMessage.Read.All, Files.Read.All)
  2. In a Teams channel, upload a PDF and @mention the bot asking about the file
  3. The bot responds that it cannot see the file
  4. Logs show [DEBUG-MEDIA] graph media fetch empty with attachmentStatus: 404

Suggested Improvements

  1. Skip Graph fallback for mention-only HTML attachments — Check if the HTML contains <attachment> tags before triggering the fallback. Pure <at> mention cards should not trigger media download.
  2. Remove the /attachments sub-resource fetch — This endpoint doesn't exist in Graph v1.0 for channel/chat messages. The attachment data is already in the message body response.
  3. Verify activity ID → Graph message ID mapping — The Bot Framework activity.id may not always correspond to the Graph API message ID for channel messages.

extent analysis

TL;DR

The bot's inability to access file content and excessive Graph API media fallback triggers can be addressed by modifying the resolveMSTeamsInboundMedia() function to skip fallback for mention-only HTML attachments and removing the unnecessary /attachments sub-resource fetch.

Guidance

  • Modify the resolveMSTeamsInboundMedia() function to check for <attachment> tags in HTML attachments before triggering the Graph API media fallback to prevent false positives for @mention messages.
  • Remove the /attachments sub-resource fetch, as attachment data is already included in the message body response, to prevent 404 errors and reduce noise in error logs.
  • Verify the mapping between Bot Framework activity.id and Graph API message ID for channel messages to ensure correct file download URLs are constructed.

Example

// Example modification to resolveMSTeamsInboundMedia()
if (attachments.length > 0 && attachments.every(att => 
    String(att.contentType ?? "").startsWith("text/html"))) {
  // Check for <attachment> tags in HTML content
  const htmlContent = att.content;
  if (htmlContent.includes("<attachment>")) {
    // Proceed with Graph API media fallback
  } else {
    // Skip fallback for mention-only HTML attachments
  }
}

Notes

The provided analysis and suggested improvements indicate that the issues are related to the handling of HTML attachments and the Graph API media fallback. However, the exact implementation details may vary depending on the specific requirements and constraints of the project.

Recommendation

Apply the suggested improvements to the resolveMSTeamsInboundMedia() function to address the issues with file access and excessive Graph API media fallback triggers. This approach should help to reduce errors and improve the overall functionality of the bot.

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

openclaw - ✅(Solved) Fix [Bug]: msteams channel file attachments not downloaded — Graph fallback triggers on non-file HTML attachments [1 pull requests, 1 participants]