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

vatsrahul1001 pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-3-test by this push:
     new b38fd5781f4 [v3-3-test] Clarify `@task` decorated callable errors when 
extra positional arguments are passed. (#69157) (#72616)
b38fd5781f4 is described below

commit b38fd5781f443c7ee84849a501e40982e3eba512
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Sep 8 14:40:42 2026 +0530

    [v3-3-test] Clarify `@task` decorated callable errors when extra positional 
arguments are passed. (#69157) (#72616)
    
    * Clarify task decorator argument errors (#49875)
    
    (cherry picked from commit 95f919523215056366d8fc88381c98ef9118d868)
    
    * Rename task decorator newsfragment for PR check (#49875)
    
    (cherry picked from commit 4e979adab39336db0488af7cfba2010fa756708d)
    
    * Narrow task decorator error hint detection (#49875)
    
    (cherry picked from commit d3143ec1e62de513f6ad085285b3175c77abf7d4)
    
    * Remove unnecessary task decorator newsfragment (#49875)
    (cherry picked from commit 1a5b65144f470118aa000a6ac52904c6bdc7c3ea)
    
    
    (cherry picked from commit ad4dc61b2a3e9ce678a6191e5e3590e0f926b7cd)
    
    Co-authored-by: Deepak Jain (DJ) <[email protected]>
---
 task-sdk/src/airflow/sdk/bases/decorator.py     | 45 ++++++++++++++++++++++---
 task-sdk/tests/task_sdk/bases/test_decorator.py | 30 +++++++++++++++++
 2 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/task-sdk/src/airflow/sdk/bases/decorator.py 
b/task-sdk/src/airflow/sdk/bases/decorator.py
index e45778725cc..2e64bc8beb3 100644
--- a/task-sdk/src/airflow/sdk/bases/decorator.py
+++ b/task-sdk/src/airflow/sdk/bases/decorator.py
@@ -253,6 +253,38 @@ def determine_kwargs(
     return KeywordParameters.determine(func, args, kwargs).unpacking()
 
 
+_TASK_DECORATOR_CALL_HINT = (
+    "This can happen when a @task-decorated function shadows another callable 
and the decorated task "
+    "object is called like a regular function. Rename the task function or 
call the original callable instead."
+)
+
+
+def _is_python_callable_already_executing(python_callable: Callable) -> bool:
+    target_code = getattr(python_callable, "__code__", None)
+    if target_code is None:
+        return False
+
+    frame = inspect.currentframe()
+    try:
+        while frame is not None:
+            if frame.f_code is target_code:
+                return True
+            frame = frame.f_back
+        return False
+    finally:
+        del frame
+
+
+def _should_add_task_decorator_call_hint(
+    err: TypeError, python_callable: Callable, op_args: Collection[Any]
+) -> bool:
+    return (
+        bool(op_args)
+        and "too many positional arguments" in str(err)
+        and _is_python_callable_already_executing(python_callable)
+    )
+
+
 class DecoratedOperator(BaseOperator):
     """
     Wraps a Python callable and captures args/kwargs when called for execution.
@@ -365,10 +397,15 @@ class DecoratedOperator(BaseOperator):
         # check all the arguments we know are valid. Whether these are enough
         # can only be known at execution time, when unmapping happens, and this
         # is called without the _airflow_mapped_validation_only flag.
-        if kwargs.get("_airflow_mapped_validation_only"):
-            signature.bind_partial(*op_args, **op_kwargs)
-        else:
-            signature.bind(*op_args, **op_kwargs)
+        try:
+            if kwargs.get("_airflow_mapped_validation_only"):
+                signature.bind_partial(*op_args, **op_kwargs)
+            else:
+                signature.bind(*op_args, **op_kwargs)
+        except TypeError as err:
+            if _should_add_task_decorator_call_hint(err, python_callable, 
op_args):
+                raise TypeError(f"{err}. {_TASK_DECORATOR_CALL_HINT}") from err
+            raise
 
         # Params in injected_for_ordering are semantically required even 
though they received a
         # None default to satisfy Python's ordering constraint. Verify they 
are actually provided.
diff --git a/task-sdk/tests/task_sdk/bases/test_decorator.py 
b/task-sdk/tests/task_sdk/bases/test_decorator.py
index 860eb6e7b33..b3dfd1630c5 100644
--- a/task-sdk/tests/task_sdk/bases/test_decorator.py
+++ b/task-sdk/tests/task_sdk/bases/test_decorator.py
@@ -189,6 +189,36 @@ class TestDefaultFillingLogic:
         with pytest.raises(TypeError):
             make_op(dummy_task)
 
+    def test_bind_validation_hints_for_accidental_task_decorator_call(self):
+        @task
+        def sleep():
+            sleep(3600)
+
+        with pytest.raises(
+            TypeError,
+            match="too many positional arguments.*@task-decorated function 
shadows another callable",
+        ):
+            sleep.function()
+
+    def 
test_bind_validation_plain_arity_error_has_no_accidental_call_hint(self):
+        @task
+        def dummy_task(required_arg):
+            return required_arg
+
+        with pytest.raises(TypeError) as ctx:
+            dummy_task(1, 2)
+
+        assert "@task-decorated function shadows another callable" not in 
str(ctx.value)
+
+    def 
test_bind_validation_missing_required_args_has_no_accidental_call_hint(self):
+        def dummy_task(required_arg):
+            return required_arg
+
+        with pytest.raises(TypeError) as ctx:
+            make_op(dummy_task)
+
+        assert "@task-decorated function shadows another callable" not in 
str(ctx.value)
+
     def test_variadic_and_keyword_only_params_are_not_assigned_defaults(self):
         """Construction succeeds when variadic and keyword-only params are 
present."""
 

Reply via email to