Skip to content

fix(slack): download all files in multi-image messages#15447

Merged
steipete merged 5 commits intoopenclaw:mainfrom
CommanderCrowCode:fix/slack-multi-image-media
Feb 14, 2026
Merged

fix(slack): download all files in multi-image messages#15447
steipete merged 5 commits intoopenclaw:mainfrom
CommanderCrowCode:fix/slack-multi-image-media

Conversation

@CommanderCrowCode
Copy link
Contributor

@CommanderCrowCode CommanderCrowCode commented Feb 13, 2026

Summary

  • resolveSlackMedia() now collects all successfully downloaded files into an array instead of returning after the first one
  • prepareSlackMessage() populates MediaPaths, MediaUrls, and MediaTypes arrays, matching the pattern used by Telegram, Line, Discord, and iMessage adapters
  • Backward compatible: single-image messages produce an array of length 1, and singular MediaPath/MediaType/MediaUrl fields are still populated from the first element

Problem

When a Slack user sends multiple images in a single message, only the first image is downloaded and processed. The resolveSlackMedia() function returns immediately after the first successful file download (return { path, contentType, placeholder }), discarding all subsequent files.

This is particularly impactful for use cases like nutrition logging where users photograph multiple dishes in one message.

Fixes #11892, #7536

Changes

src/slack/monitor/media.ts

  • Changed resolveSlackMedia() return type from Promise<{path, contentType, placeholder} | null> to Promise<SlackMediaResult[] | null>
  • The loop now pushes each result to an array instead of returning early
  • Added exported SlackMediaResult type

src/slack/monitor/message-handler/prepare.ts

  • rawBody placeholder: joins all file placeholders with spaces
  • effectiveMedia context fields: MediaPath/MediaType/MediaUrl use first element; new MediaPaths/MediaUrls/MediaTypes arrays carry all elements
  • Thread starter media log message updated for array format

src/slack/monitor/media.test.ts

  • Added assertion that error-fallback test returns array of length 1
  • Added new test: "returns all successfully downloaded files as an array" — verifies both files are returned with correct paths and placeholders

Test plan

  • Existing resolveSlackMedia tests pass with updated assertions
  • New multi-file test verifies both files are returned
  • Single-image Slack messages continue to work (array of 1)
  • Multi-image Slack messages now process all images
  • MediaPath singular field still populated (backward compat)

🤖 Generated with Claude Code

Greptile Overview

Greptile Summary

This PR updates Slack inbound media handling to support multi-file messages: resolveSlackMedia() now downloads all successfully fetched attachments and returns them as an array, and prepareSlackMessage() populates both legacy single-value media fields and new MediaPaths/MediaUrls/MediaTypes arrays.

Main issue to address before merge: MediaTypes is currently derived with a filter(Boolean) which can shrink the array and break index alignment with MediaPaths/MediaUrls. Several downstream components treat these arrays as index-correlated (or require equal lengths), so this can cause MIME hints to be dropped or misapplied for multi-attachment messages.

Confidence Score: 4/5

  • Mostly safe to merge, but fix MediaTypes index alignment for multi-attachment messages first.
  • Core change (returning an array from resolveSlackMedia and plumbing MediaPaths/Urls/Types) is straightforward and test-covered. The remaining issue is a concrete data-shape bug: filtering falsy MediaTypes values can desync arrays and break downstream assumptions about attachment indexing.
  • src/slack/monitor/message-handler/prepare.ts

Last reviewed commit: ddfb393

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

@openclaw-barnacle openclaw-barnacle bot added channel: slack Channel integration: slack size: S labels Feb 13, 2026
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +615 to +618
MediaTypes:
effectiveMedia && effectiveMedia.length > 0
? (effectiveMedia.map((m) => m.contentType).filter(Boolean) as string[])
: undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

Misaligned MediaTypes array

MediaTypes is built with effectiveMedia.map((m) => m.contentType).filter(Boolean), which can shorten the array compared to MediaPaths/MediaUrls when any attachment lacks a contentType. Downstream code treats these arrays as index-aligned (and in some places requires equal lengths), so this drops MIME hints for multi-attachment messages and can mis-associate types. Prefer keeping MediaTypes the same length/order as MediaPaths (e.g., preserve undefined entries) so indices remain consistent.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/slack/monitor/message-handler/prepare.ts
Line: 615:618

Comment:
**Misaligned MediaTypes array**

`MediaTypes` is built with `effectiveMedia.map((m) => m.contentType).filter(Boolean)`, which can shorten the array compared to `MediaPaths`/`MediaUrls` when any attachment lacks a `contentType`. Downstream code treats these arrays as index-aligned (and in some places requires equal lengths), so this drops MIME hints for multi-attachment messages and can mis-associate types. Prefer keeping `MediaTypes` the same length/order as `MediaPaths` (e.g., preserve `undefined` entries) so indices remain consistent.

How can I resolve this? If you propose a fix, please make it concise.

@steipete steipete self-assigned this Feb 14, 2026
@steipete steipete force-pushed the fix/slack-multi-image-media branch from e99a2ac to d433773 Compare February 14, 2026 12:47
steipete added a commit to CommanderCrowCode/openclaw that referenced this pull request Feb 14, 2026
CommanderCrowCode and others added 4 commits February 14, 2026 13:47
resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…Urls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@steipete steipete force-pushed the fix/slack-multi-image-media branch from d433773 to da64c9e Compare February 14, 2026 13:06
@openclaw-barnacle openclaw-barnacle bot added scripts Repository scripts channel: feishu Channel integration: feishu labels Feb 14, 2026
@steipete steipete merged commit c76288b into openclaw:main Feb 14, 2026
13 checks passed
@steipete
Copy link
Contributor

Merged via squash.

Thanks @CommanderCrowCode!

hamidzr pushed a commit to hamidzr/openclaw that referenced this pull request Feb 14, 2026
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): align MediaType fallback and tests (openclaw#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (openclaw#15447)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
openperf pushed a commit to openperf/moltbot that referenced this pull request Feb 14, 2026
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): align MediaType fallback and tests (openclaw#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (openclaw#15447)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
openperf pushed a commit to openperf/moltbot that referenced this pull request Feb 14, 2026
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): align MediaType fallback and tests (openclaw#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (openclaw#15447)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
BigUncle pushed a commit to BigUncle/openclaw that referenced this pull request Feb 14, 2026
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): align MediaType fallback and tests (openclaw#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (openclaw#15447)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
mverrilli pushed a commit to mverrilli/openclaw that referenced this pull request Feb 14, 2026
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): align MediaType fallback and tests (openclaw#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (openclaw#15447)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
GwonHyeok pushed a commit to learners-superpumped/openclaw that referenced this pull request Feb 15, 2026
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): align MediaType fallback and tests (openclaw#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (openclaw#15447)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 1, 2026
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): align MediaType fallback and tests (openclaw#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (openclaw#15447)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
(cherry picked from commit c76288b)

# Conflicts:
#	src/slack/monitor/media.test.ts
#	src/slack/monitor/media.ts
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 3, 2026
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slack): align MediaType fallback and tests (openclaw#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (openclaw#15447)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
(cherry picked from commit c76288b)

# Conflicts:
#	extensions/feishu/package.json
#	scripts/write-plugin-sdk-entry-dts.ts
#	src/slack/monitor/media.test.ts
#	src/slack/monitor/media.ts
#	src/slack/monitor/message-handler/prepare.ts
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
* fix(slack): download all files in multi-image messages

resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.

The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.

Fixes openclaw#11892, openclaw#7536


* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls

The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".


* fix(slack): align MediaType fallback and tests (openclaw#15447) (thanks @CommanderCrowCode)

* fix: unblock plugin-sdk account-id typing (openclaw#15447)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: feishu Channel integration: feishu channel: slack Channel integration: slack scripts Repository scripts size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slack: only first file attachment is processed when multiple files are sent in one message

2 participants