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_v2 — SlackAdapter 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
- 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.
- Audit other adapter call sites for similar kwarg-rename drift between slack-sdk releases (
files.upload → files_upload_v2 was a known cleanup that shifted naming around).
Happy to send a PR if useful — let me know.
Summary
SlackAdapter._upload_files(chat_sdk/adapters/slack/adapter.py) callsclient.files_upload_v2(channel_id=channel, ...). With recentslack-sdk(≥3.x),files_upload_v2's documented kwarg ischannel, notchannel_id. slack-sdk forwards arbitrary kwargs into its internalfiles_completeUploadExternalcall AND adds its ownchannel_idthere — producing a hardTypeErroron every Slack file upload. No file upload via this adapter can succeed today.Affected versions
chat-sdk[slack,teams,postgres] @ git+…@v0.4.26.2)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:Root cause
chat_sdk/adapters/slack/adapter.pylines 2638-2643 (in_upload_files):slack-sdk'sAsyncWebClient.files_upload_v2(slack_sdk/web/async_client.py:~3950) signature useschannel: Optional[str]. Any extra kwargs (includingchannel_id) are passed through to the internalfiles_completeUploadExternalcall (which derives its ownchannel_idfromchannel) — 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).(Apply the same fix to any other adapter helper that wraps
files_upload_v2—SlackAdapterhad 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_filesby extracting the underlyingAsyncWebClientand calling slack-sdk directly with the correct kwarg:We've shipped this bypass in
Chinchill-AI/chinchill-api#1138so production isn't waiting on a release here, but we'd love to drop the bypass once the upstream fix lands.Suggested follow-ups
_upload_filespasseschannel=(notchannel_id=) to the slack client (mock the client, assert call args). Catches any future rename.files.upload→files_upload_v2was a known cleanup that shifted naming around).Happy to send a PR if useful — let me know.