This is an automated email from the ASF dual-hosted git repository.

eladkal pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new e248b24a376 Validate `thread_ts` requires single channel in 
`SlackAPIFileOperator` (#63523)
e248b24a376 is described below

commit e248b24a376922559cbd80cffdb44463f6cb2928
Author: yuseok89 <[email protected]>
AuthorDate: Sat Mar 14 23:39:44 2026 +0900

    Validate `thread_ts` requires single channel in `SlackAPIFileOperator` 
(#63523)
---
 providers/slack/src/airflow/providers/slack/hooks/slack.py     |  6 ++++++
 providers/slack/src/airflow/providers/slack/operators/slack.py |  4 ++--
 providers/slack/tests/unit/slack/hooks/test_slack.py           | 10 ++++++++++
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/providers/slack/src/airflow/providers/slack/hooks/slack.py 
b/providers/slack/src/airflow/providers/slack/hooks/slack.py
index ac6d83c518f..2a5f79339a4 100644
--- a/providers/slack/src/airflow/providers/slack/hooks/slack.py
+++ b/providers/slack/src/airflow/providers/slack/hooks/slack.py
@@ -310,6 +310,12 @@ class SlackHook(BaseHook):
         else:
             channels_to_share = [None]
 
+        if thread_ts is not None and len(channels_to_share) > 1:
+            raise ValueError(
+                "thread_ts cannot be used with multiple channels. "
+                "A thread belongs to a single channel; specify exactly one 
channel when replying in a thread."
+            )
+
         responses = []
         for channel in channels_to_share:
             responses.append(
diff --git a/providers/slack/src/airflow/providers/slack/operators/slack.py 
b/providers/slack/src/airflow/providers/slack/operators/slack.py
index 56b4c90a387..421ebfb8c9b 100644
--- a/providers/slack/src/airflow/providers/slack/operators/slack.py
+++ b/providers/slack/src/airflow/providers/slack/operators/slack.py
@@ -228,8 +228,8 @@ class SlackAPIFileOperator(SlackAPIOperator):
     :param snippet_type: Syntax type for the snippet being uploaded.(templated)
     :param method_version: The version of the method of Slack SDK Client to be 
used, either "v1" or "v2".
     :param thread_ts: Provide another message's ``ts`` value to upload the 
file as a reply in a
-        thread. See https://api.slack.com/messaging#threading (templated)
-
+        thread. See https://api.slack.com/messaging#threading. When using 
``thread_ts``, specify
+        exactly one channel in ``channels``; a thread belongs to a single 
channel. (templated)
     :return: List of Slack API response data from ``files_upload_v2`` (one per 
channel).
         Returned value is pushed to XCom for downstream tasks.
     """
diff --git a/providers/slack/tests/unit/slack/hooks/test_slack.py 
b/providers/slack/tests/unit/slack/hooks/test_slack.py
index 1de8c06a0ea..3e7d94df33f 100644
--- a/providers/slack/tests/unit/slack/hooks/test_slack.py
+++ b/providers/slack/tests/unit/slack/hooks/test_slack.py
@@ -567,6 +567,16 @@ class TestSlackHook:
             hook.send_file_v1_to_v2(channels=channels, content="Fake")
             assert mocked_send_file_v2.call_count == expected_calls
 
+    def test_send_file_v1_to_v2_thread_ts_with_multiple_channels_raises(self):
+        """thread_ts with multiple channels is invalid; a thread belongs to 
one channel."""
+        hook = SlackHook(slack_conn_id=SLACK_API_DEFAULT_CONN_ID)
+        with pytest.raises(ValueError, match="thread_ts.*single channel"):
+            hook.send_file_v1_to_v2(
+                channels="#general,#random",
+                content="Fake",
+                thread_ts="1234567890.123456",
+            )
+
 
 class TestSlackHookAsync:
     @pytest.fixture

Reply via email to