Skip to content

fix(slack): replace files.uploadV2 with 3-step upload flow to fix missing_scope error#17558

Merged
Takhoffman merged 2 commits intoopenclaw:mainfrom
fif911:fix/slack-file-upload-missing-scope
Mar 1, 2026
Merged

fix(slack): replace files.uploadV2 with 3-step upload flow to fix missing_scope error#17558
Takhoffman merged 2 commits intoopenclaw:mainfrom
fif911:fix/slack-file-upload-missing-scope

Conversation

@fif911
Copy link
Contributor

@fif911 fif911 commented Feb 15, 2026

Problem

uploadSlackFile() uses client.files.uploadV2() from @slack/web-api, which internally calls the deprecated files.upload endpoint. This fails with missing_scope even when files:write is correctly granted in the bot token scopes.

The direct REST API (files.getUploadURLExternal → upload → files.completeUploadExternal) works fine with the same token, confirming the scope is present but the SDK method uses a different code path.

Fix

Replace the single files.uploadV2() call with Slack's recommended 3-step upload flow:

  1. files.getUploadURLExternal — get presigned upload URL + file_id
  2. fetch(upload_url) — upload file content to presigned URL
  3. files.completeUploadExternal — finalize & share to channel/thread

Changes

  • 1 file changed: src/slack/send.ts
  • Only the uploadSlackFile() function body is modified
  • Function signature unchanged
  • All existing behavior preserved (channel uploads, thread replies via thread_ts, captions via initial_comment)
  • Removed unused FilesUploadV2Arguments type import

Testing

Manually verified the 3-step flow works correctly:

  • ✅ Channel upload (file shared to channel with caption)
  • ✅ Thread reply upload (file shared in thread with thread_ts)
  • ✅ Same bot token, same files:write scope — no more missing_scope error

Greptile Summary

This PR replaces the broken files.uploadV2() SDK call in uploadSlackFile() with Slack's recommended 3-step upload flow: getUploadURLExternal → presigned URL POST → completeUploadExternal. The change fixes missing_scope errors that occurred because files.uploadV2 internally uses the deprecated files.upload endpoint.

  • The implementation is clean and well-structured with explicit error handling at each step
  • Function signature and all existing behavior (channel uploads, thread replies via thread_ts, captions via initial_comment) are preserved
  • The return value semantics remain the same — both old and new code return a Slack file ID, not a message timestamp. This is a pre-existing limitation where messageId in SlackSendResult won't be a valid Slack ts for file-only uploads (affecting downstream operations like reactions/edits), but this PR does not change that behavior
  • The unused FilesUploadV2Arguments import is correctly removed
  • CHANGELOG entry is accurate

Confidence Score: 4/5

  • This PR is safe to merge — it fixes a real Slack API compatibility issue with a well-structured replacement that preserves all existing behavior.
  • Score of 4 reflects that this is a focused, well-implemented fix for a known Slack SDK issue. The 3-step upload flow follows Slack's recommended approach, error handling is thorough, and existing behavior is preserved. Minor deduction because the Content-Type header is not forwarded to the presigned URL upload (style concern, not a functional bug).
  • No files require special attention. The change is isolated to the uploadSlackFile function body in src/slack/send.ts.

Last reviewed commit: 30ee226

@openclaw-barnacle openclaw-barnacle bot added channel: slack Channel integration: slack size: S labels Feb 15, 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.

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@steipete steipete closed this Feb 16, 2026
@steipete steipete reopened this Feb 17, 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.

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 17, 2026

Additional Comments (1)

src/slack/send.ts
Missing Content-Type header on presigned URL upload
The contentType from loadWebMedia is extracted on line 181 (as _contentType) but not forwarded to the presigned URL upload. While Slack's presigned URL endpoint generally accepts raw bytes without a Content-Type header, setting it explicitly ensures the file's MIME type is correctly recorded server-side — especially for non-obvious file types. Consider passing it through:

  const uploadResp = await fetch(uploadUrlResp.upload_url, {
    method: "POST",
    headers: _contentType ? { "Content-Type": _contentType } : {},
    body: new Uint8Array(buffer) as BodyInit,
  });

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/slack/send.ts
Line: 199:202

Comment:
**Missing Content-Type header on presigned URL upload**
The `contentType` from `loadWebMedia` is extracted on line 181 (as `_contentType`) but not forwarded to the presigned URL upload. While Slack's presigned URL endpoint generally accepts raw bytes without a `Content-Type` header, setting it explicitly ensures the file's MIME type is correctly recorded server-side — especially for non-obvious file types. Consider passing it through:

```suggestion
  const uploadResp = await fetch(uploadUrlResp.upload_url, {
    method: "POST",
    headers: _contentType ? { "Content-Type": _contentType } : {},
    body: new Uint8Array(buffer) as BodyInit,
  });
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

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

@fif911
Copy link
Contributor Author

fif911 commented Feb 18, 2026

@steipete is there anything to fix here? this essentially fixes the file upload in Slack thread. Now the agent would fail to attach the file to the thread (only attaching into the channel and DMs will work without this fix)

fif911 and others added 2 commits March 1, 2026 11:32
files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.
@Takhoffman Takhoffman force-pushed the fix/slack-file-upload-missing-scope branch from 30ee226 to 3b80205 Compare March 1, 2026 17:37
@Takhoffman Takhoffman merged commit 2a409bb into openclaw:main Mar 1, 2026
9 checks passed
zooqueen added a commit to hanzoai/bot that referenced this pull request Mar 1, 2026
ansh pushed a commit to vibecode/openclaw that referenced this pull request Mar 2, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
steipete pushed a commit to Sid-Qin/openclaw that referenced this pull request Mar 2, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
safzanpirani pushed a commit to safzanpirani/clawdbot that referenced this pull request Mar 2, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
steipete pushed a commit to Sid-Qin/openclaw that referenced this pull request Mar 2, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
amitmiran137 pushed a commit to amitmiran137/openclaw that referenced this pull request Mar 2, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
robertchang-ga pushed a commit to robertchang-ga/openclaw that referenced this pull request Mar 2, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
hanqizheng pushed a commit to hanqizheng/openclaw that referenced this pull request Mar 2, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
robertchang-ga pushed a commit to robertchang-ga/openclaw that referenced this pull request Mar 2, 2026
execute008 pushed a commit to execute008/openclaw that referenced this pull request Mar 2, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
dorgonman pushed a commit to kanohorizonia/openclaw that referenced this pull request Mar 3, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
@fif911 fif911 deleted the fix/slack-file-upload-missing-scope branch March 3, 2026 10:06
sachinkundu pushed a commit to sachinkundu/openclaw that referenced this pull request Mar 6, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
…sing_scope error (openclaw#17558)

* fix(slack): replace files.uploadV2 with 3-step upload flow

files.uploadV2 from @slack/web-api internally calls the deprecated
files.upload endpoint, which fails with missing_scope even when
files:write is correctly granted in the bot token scopes.

Replace with Slack's recommended 3-step upload flow:
1. files.getUploadURLExternal - get presigned URL + file_id
2. fetch(upload_url) - upload file content
3. files.completeUploadExternal - finalize & share to channel/thread

This preserves all existing behavior including thread replies via
thread_ts and caption via initial_comment.

* fix(slack): harden external upload flow and tests

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
zooqueen added a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants