Skip to content

Slack download-file fails silently on Node.js v25 — globalThis.fetch does not support dispatcher option #63393

@danielhernandez94

Description

@danielhernandez94

Bug

message(action="download-file") for Slack files always returns "File could not be downloaded (not found, too large, or inaccessible)." even when the file exists and the bot token has files:read scope.

Root Cause

createSlackMediaFetch in extensions/slack/src/actions.ts calls globalThis.fetch() and passes through the dispatcher option from the SSRF guard's fetchWithSsrFGuard. In Node.js v25, globalThis.fetch does not support the dispatcher option (only undici.fetch does), causing a TypeError: fetch failed.

The error is silently swallowed by the catch {} in resolveSlackMedia, making the download return null with no logging.

Reproduction

  1. Have a Slack file attachment in any channel
  2. Call message(action="download-file", channel="slack", fileId="F...")
  3. Always returns error, even though files.info API and direct curl with the bot token both work fine
// This fails in Node.js v25:
globalThis.fetch(url, { dispatcher: new undici.Agent(), redirect: 'manual' })
// TypeError: fetch failed

// This works:
undici.fetch(url, { dispatcher: new undici.Agent(), redirect: 'manual' })

Fix

Strip dispatcher from the options before passing to globalThis.fetch in createSlackMediaFetch:

- const { headers: initHeaders, redirect: _redirect, ...rest } = init ?? {};
+ const { headers: initHeaders, redirect: _redirect, dispatcher: _dispatcher, ...rest } = init ?? {};

The SSRF DNS validation still runs upstream in fetchWithSsrFGuard — the dispatcher was only needed for DNS pinning which already completed before the custom fetch is called.

Environment

  • OpenClaw: 2026.4.5
  • Node.js: v25.6.1
  • Platform: macOS arm64

Additional Note

The catch {} in resolveSlackMedia should ideally log the error rather than silently swallowing it, to make debugging easier.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions