Skip to content

SlackAdapter._upload_files passes channel_id= to slack-sdk files_upload_v2 → TypeError "got multiple values for keyword argument 'channel_id'" #102

@patrick-chinchill

Description

@patrick-chinchill

Summary

SlackAdapter._upload_files (chat_sdk/adapters/slack/adapter.py) calls client.files_upload_v2(channel_id=channel, ...). With recent slack-sdk (≥3.x), files_upload_v2's documented kwarg is channel, not channel_id. slack-sdk forwards arbitrary kwargs into its internal files_completeUploadExternal call AND adds its own channel_id there — producing a hard TypeError on every Slack file upload. No file upload via this adapter can succeed today.

Affected versions

  • chat-sdk-python v0.4.26.2 (pinned via chat-sdk[slack,teams,postgres] @ git+…@v0.4.26.2)
  • slack-sdk 3.37.0

Observed (production)

Logfire-captured stack from customer-ase-dev (chinchill-api app, 2026-05-28 02:56:24Z), reproducing on every chart-generating Slack reply:

TypeError: slack_sdk.web.async_client.AsyncWebClient.files_completeUploadExternal()
           got multiple values for keyword argument 'channel_id'

  File ".../chat_sdk/adapters/slack/adapter.py", line 2122, in post_message
    self._handle_slack_error(error)
  File ".../chat_sdk/adapters/slack/adapter.py", line 3045, in _handle_slack_error
    raise error
  File ".../chat_sdk/adapters/slack/adapter.py", line 2049, in post_message
    await self._upload_files(files, channel, thread_ts or None)
  File ".../chat_sdk/adapters/slack/adapter.py", line 2643, in _upload_files
    result = await client.files_upload_v2(**kwargs)
  File ".../slack_sdk/web/async_client.py", line 4040, in files_upload_v2
    completion = await self.files_completeUploadExternal(...)
TypeError: ... got multiple values for keyword argument 'channel_id'

Root cause

chat_sdk/adapters/slack/adapter.py lines 2638-2643 (in _upload_files):

client = self._get_client()
kwargs: dict[str, Any] = {"channel_id": channel, "file_uploads": file_uploads}  # ← bug: should be "channel"
if thread_ts:
    kwargs["thread_ts"] = thread_ts

result = await client.files_upload_v2(**kwargs)

slack-sdk's AsyncWebClient.files_upload_v2 (slack_sdk/web/async_client.py:~3950) signature uses channel: Optional[str]. Any extra kwargs (including channel_id) are passed through to the internal files_completeUploadExternal call (which derives its own channel_id from channel) — colliding.

One-line fix

Change "channel_id""channel" on the kwargs dict at line 2639. Any internal references to that key elsewhere in the function need the same rename (none observed in this code path).

- kwargs: dict[str, Any] = {"channel_id": channel, "file_uploads": file_uploads}
+ kwargs: dict[str, Any] = {"channel": channel, "file_uploads": file_uploads}

(Apply the same fix to any other adapter helper that wraps files_upload_v2SlackAdapter had only one such site when I checked v0.4.26.2.)

Workaround (consumer-side, in case anyone else hits this before a release)

Bypass _upload_files by extracting the underlying AsyncWebClient and calling slack-sdk directly with the correct kwarg:

adapter = post_target.adapter
client = adapter._get_client()
decoded = adapter.decode_thread_id(post_target.id)
await client.files_upload_v2(
    channel=decoded.channel,
    thread_ts=decoded.thread_ts or None,
    file_uploads=[{"file": bytes_, "filename": name} for ...],
    initial_comment=...,
)

We've shipped this bypass in Chinchill-AI/chinchill-api#1138 so production isn't waiting on a release here, but we'd love to drop the bypass once the upstream fix lands.

Suggested follow-ups

  1. Add a test that asserts _upload_files passes channel= (not channel_id=) to the slack client (mock the client, assert call args). Catches any future rename.
  2. Audit other adapter call sites for similar kwarg-rename drift between slack-sdk releases (files.uploadfiles_upload_v2 was a known cleanup that shifted naming around).

Happy to send a PR if useful — let me know.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingslack

    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