Description
Teams file attachments (documents, images sent in DMs) fail to download silently on Node 24+ (tested on v24.13.1, v25.7.0, v25.8.1, v25.8.2). The Graph API message fetch succeeds, SharePoint reference attachments are visible in the response, but the actual file content download via /shares/u!.../driveItem/content fails with:
MediaFetchError: Failed to fetch media from .../driveItem/content: fetch failed | invalid onRequestStart method
cause: TypeError: fetch failed
The error is swallowed by an empty catch {} in the SharePoint download loop, resulting in "graph media fetch empty" at debug level with no indication of the root cause.
Root Cause
fetchRemoteMedia in fetch-BgzO65-j.js always uses withStrictGuardedFetchMode, which triggers createPinnedDispatcher in ssrf-8K2hYwIJ.js. The pinned dispatcher creates an undici.Agent with a custom connect.lookup for DNS pinning. On Node 24+ (which ships undici v7), the dispatcher handler API changed — the onRequestStart method signature is incompatible, causing an immediate TypeError: fetch failed before any network request is made.
This does NOT affect the Graph message fetch (which uses fetchWithSsrFGuard in non-strict mode via safeFetchWithPolicy), only the fetchRemoteMedia path used for downloading file content.
Impact
- All Teams DM file attachments (documents, PDFs, images sent as files) silently fail
- The
<media:document> tag appears in the agent's input but no file content is delivered
- No visible error at INFO log level — only discoverable via debug logging or code instrumentation
Reproduction
- Run OpenClaw on Node 24+ with Teams configured
- Send a file attachment in a Teams DM to the bot
- The agent receives
<media:document> but no file content
- Debug logs show "graph media fetch empty"
Workaround
Bypass fetchRemoteMedia in downloadAndStoreMSTeamsRemoteMedia by replacing the fetchRemoteMedia call with a direct fetch using the existing custom fetchImpl (which already handles auth headers and allowlist validation via safeFetchWithPolicy):
// In downloadAndStoreMSTeamsRemoteMedia, replace:
const fetched = await getMSTeamsRuntime().channel.media.fetchRemoteMedia({
url: params.url,
fetchImpl: params.fetchImpl,
filePathHint: params.filePathHint,
maxBytes: params.maxBytes,
ssrfPolicy: params.ssrfPolicy
});
// With:
let fetched;
const fetchFn = params.fetchImpl || fetch;
const res = await fetchFn(params.url, { redirect: "follow" });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
if (params.maxBytes && buffer.byteLength > params.maxBytes) throw new Error("File too large");
fetched = { buffer, contentType: res.headers.get("content-type") || "application/octet-stream" };
The URL has already been validated by isUrlAllowed() before reaching downloadAndStoreMSTeamsRemoteMedia, so skipping the strict SSRF dispatcher is safe for this code path.
Additional Note
Teams file attachments also require Files.Read.All (Application) permission on the Azure bot app registration — without it, the Graph sharing API returns 403. This is not documented in the OpenClaw Teams setup guide. The Chat.Read.All and ChatMessage.Read.All permissions are insufficient for downloading file content.
Related
Environment
- OpenClaw: 2026.4.5, 2026.4.8
- Node: v24.13.1, v25.7.0, v25.8.1, v25.8.2
- Platform: Ubuntu 24.04, macOS
- Channel: Microsoft Teams (personal DMs)
Description
Teams file attachments (documents, images sent in DMs) fail to download silently on Node 24+ (tested on v24.13.1, v25.7.0, v25.8.1, v25.8.2). The Graph API message fetch succeeds, SharePoint
referenceattachments are visible in the response, but the actual file content download via/shares/u!.../driveItem/contentfails with:The error is swallowed by an empty
catch {}in the SharePoint download loop, resulting in "graph media fetch empty" at debug level with no indication of the root cause.Root Cause
fetchRemoteMediainfetch-BgzO65-j.jsalways useswithStrictGuardedFetchMode, which triggerscreatePinnedDispatcherinssrf-8K2hYwIJ.js. The pinned dispatcher creates anundici.Agentwith a customconnect.lookupfor DNS pinning. On Node 24+ (which ships undici v7), the dispatcher handler API changed — theonRequestStartmethod signature is incompatible, causing an immediateTypeError: fetch failedbefore any network request is made.This does NOT affect the Graph message fetch (which uses
fetchWithSsrFGuardin non-strict mode viasafeFetchWithPolicy), only thefetchRemoteMediapath used for downloading file content.Impact
<media:document>tag appears in the agent's input but no file content is deliveredReproduction
<media:document>but no file contentWorkaround
Bypass
fetchRemoteMediaindownloadAndStoreMSTeamsRemoteMediaby replacing thefetchRemoteMediacall with a directfetchusing the existing customfetchImpl(which already handles auth headers and allowlist validation viasafeFetchWithPolicy):The URL has already been validated by
isUrlAllowed()before reachingdownloadAndStoreMSTeamsRemoteMedia, so skipping the strict SSRF dispatcher is safe for this code path.Additional Note
Teams file attachments also require
Files.Read.All(Application) permission on the Azure bot app registration — without it, the Graph sharing API returns 403. This is not documented in the OpenClaw Teams setup guide. TheChat.Read.AllandChatMessage.Read.Allpermissions are insufficient for downloading file content.Related
Environment