Skip to content

Commit 90a13ee

Browse files
Add warnings when Node returns value but outputs=None (#5356)
This PR adds validation for the outputs=None case in node._outputs_to_dictionary(). If a node function returns a value while outputs=None, Kedro now emits a clear, actionable warning explaining that the return value will be ignored and how to fix the node definition.
1 parent 9cc94d0 commit 90a13ee

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

kedro/pipeline/node.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,16 @@ def _from_list() -> dict:
663663
return dict(zip(self._outputs, result))
664664

665665
if self._outputs is None:
666+
if outputs is not None:
667+
node_name = self._name or self._func_name
668+
warnings.warn(
669+
f"Node '{node_name}' returned a value of type "
670+
f"'{type(outputs).__name__}', but the node is defined with outputs=None. "
671+
"Kedro ignores return values for nodes without declared outputs. "
672+
"If this return value is intentional, declare outputs in the node "
673+
"definition to include it in the pipeline.",
674+
UserWarning,
675+
)
666676
return {}
667677
if isinstance(self._outputs, str):
668678
return {self._outputs: outputs}

tests/pipeline/test_node_run.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import warnings
2+
13
import pytest
24

35
from kedro.pipeline import node
@@ -141,3 +143,40 @@ def one_in_two_out(arg):
141143
pattern += r"the node definition contains 3 output\(s\)\."
142144
with pytest.raises(ValueError, match=pattern):
143145
node(one_in_two_out, "ds1", ["A", "B", "C"]).run({"ds1": mocked_dataset})
146+
147+
148+
class TestNodeOutputsNoneWarning:
149+
"""Test warning behavior when outputs=None but function returns a value."""
150+
151+
@pytest.mark.parametrize(
152+
"return_value,expected_type",
153+
[
154+
({"r2_score": 0.95}, "dict"),
155+
([1, 2, 3], "list"),
156+
(42, "int"),
157+
],
158+
)
159+
def test_outputs_none_warns_when_value_returned(self, return_value, expected_type):
160+
def func(_):
161+
return return_value
162+
163+
test_node = node(func, "input", None, name="test_node")
164+
pattern = (
165+
rf"Node 'test_node' returned a value of type '{expected_type}', "
166+
r"but the node is defined with outputs=None\. "
167+
r"Kedro ignores return values for nodes without declared outputs\. "
168+
r"If this return value is intentional, declare outputs in the node "
169+
r"definition to include it in the pipeline\."
170+
)
171+
with pytest.warns(UserWarning, match=pattern):
172+
test_node.run({"input": 42})
173+
174+
def test_outputs_none_does_not_warn_when_none_returned(self):
175+
def func(_):
176+
return None
177+
178+
test_node = node(func, "input", None, name="test_node")
179+
with warnings.catch_warnings():
180+
warnings.simplefilter("error")
181+
result = test_node.run({"input": 42})
182+
assert result == {}

0 commit comments

Comments
 (0)