Repository: kedro-org/kedro

Issue:
Improve error message when passing wrong value to `node` - AttributeError: ‘int’ object has no attribute ‘split’
## Description
Is your feature request related to a problem? A clear and concise description of what the problem is: "I'm always frustrated when ..."

Node is suppose to take name of datasets (or parmaeters), when users put a value in node, they get an obscure error.
```py
node(
    func=split_data,
    inputs=["example_iris_data", "parameters"],
    outputs={"X_train":1},
    name="split",
),
```

> AttributeError: 'int' object has no attribute 'split'

See full traceback:
<summary><details>

```
> ╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
> │ /Users/Nok_Lam_Chan/miniconda3/envs/kedro_core/bin/kedro:8 in <module>                           │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/framework/cli/cli.py:211 in main                          │
> │                                                                                                  │
> │   208 │   """                                                                                    │
> │   209 │   _init_plugins()                                                                        │
> │   210 │   cli_collection = KedroCLI(project_path=Path.cwd())                                     │
> │ ❱ 211 │   cli_collection()                                                                       │
> │   212                                                                                            │
> │                                                                                                  │
> │ ╭───────────── locals ─────────────╮                                                             │
> │ │ cli_collection = <KedroCLI None> │                                                             │
> │ ╰──────────────────────────────────╯                                                             │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/miniconda3/envs/kedro_core/lib/python3.8/site-packages/click/core.py:1130 in │
> │ __call__                                                                                         │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/framework/cli/cli.py:139 in main                          │
> │                                                                                                  │
> │   136 │   │   )                                                                                  │
> │   137 │   │                                                                                      │
> │   138 │   │   try:                                                                               │
> │ ❱ 139 │   │   │   super().main(                                                                  │
> │   140 │   │   │   │   args=args,                                                                 │
> │   141 │   │   │   │   prog_name=prog_name,                                                       │
> │   142 │   │   │   │   complete_var=complete_var,                                                 │
> │                                                                                                  │
> │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
> │ │       __class__ = <class 'kedro.framework.cli.cli.KedroCLI'>                                 │ │
> │ │            args = ['run']                                                                    │ │
> │ │    complete_var = None                                                                       │ │
> │ │           extra = {                                                                          │ │
> │ │                   │   'obj': ProjectMetadata(                                                │ │
> │ │                   │   │                                                                      │ │
> │ │                   config_file=PosixPath('/Users/Nok_Lam_Chan/GitHub/kedro/richlog/pyproject… │ │
> │ │                   │   │   package_name='richlog',                                            │ │
> │ │                   │   │   project_name='richlog',                                            │ │
> │ │                   │   │                                                                      │ │
> │ │                   project_path=PosixPath('/Users/Nok_Lam_Chan/GitHub/kedro/richlog'),        │ │
> │ │                   │   │   project_version='0.18.7',                                          │ │
> │ │                   │   │                                                                      │ │
> │ │                   source_dir=PosixPath('/Users/Nok_Lam_Chan/GitHub/kedro/richlog/src'),      │ │
> │ │                   │   │   kedro_init_version='0.18.7'                                        │ │
> │ │                   │   )                                                                      │ │
> │ │                   }                                                                          │ │
> │ │       prog_name = None                                                                       │ │
> │ │            self = <KedroCLI None>                                                            │ │
> │ │ standalone_mode = True                                                                       │ │
> │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/miniconda3/envs/kedro_core/lib/python3.8/site-packages/click/core.py:1055 in │
> │ main                                                                                             │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/miniconda3/envs/kedro_core/lib/python3.8/site-packages/click/core.py:1657 in │
> │ invoke                                                                                           │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/miniconda3/envs/kedro_core/lib/python3.8/site-packages/click/core.py:1404 in │
> │ invoke                                                                                           │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/miniconda3/envs/kedro_core/lib/python3.8/site-packages/click/core.py:760 in  │
> │ invoke                                                                                           │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/framework/cli/project.py:459 in run                       │
> │                                                                                                  │
> │   456 │   with KedroSession.create(                                                              │
> │   457 │   │   env=env, conf_source=conf_source, extra_params=params                              │
> │   458 │   ) as session:                                                                          │
> │ ❱ 459 │   │   session.run(                                                                       │
> │   460 │   │   │   tags=tag,                                                                      │
> │   461 │   │   │   runner=runner(is_async=is_async),                                              │
> │   462 │   │   │   node_names=node_names,                                                         │
> │                                                                                                  │
> │ ╭──────────────────────────────────────── locals ─────────────────────────────────────────╮      │
> │ │   conf_source = None                                                                    │      │
> │ │        config = None                                                                    │      │
> │ │           env = None                                                                    │      │
> │ │   from_inputs = []                                                                      │      │
> │ │    from_nodes = []                                                                      │      │
> │ │      is_async = False                                                                   │      │
> │ │  load_version = {}                                                                      │      │
> │ │ load_versions = {}                                                                      │      │
> │ │     namespace = None                                                                    │      │
> │ │    node_names = ()                                                                      │      │
> │ │   nodes_names = ()                                                                      │      │
> │ │        params = {}                                                                      │      │
> │ │      pipeline = None                                                                    │      │
> │ │        runner = <class 'kedro.runner.sequential_runner.SequentialRunner'>               │      │
> │ │       session = <kedro.framework.session.session.KedroSession object at 0x7f8c90dfc5e0> │      │
> │ │           tag = ()                                                                      │      │
> │ │          tags = ()                                                                      │      │
> │ │      to_nodes = []                                                                      │      │
> │ │    to_outputs = []                                                                      │      │
> │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯      │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/framework/session/session.py:376 in run                   │
> │                                                                                                  │
> │   373 │   │   name = pipeline_name or "__default__"                                              │
> │   374 │   │                                                                                      │
> │   375 │   │   try:                                                                               │
> │ ❱ 376 │   │   │   pipeline = pipelines[name]                                                     │
> │   377 │   │   except KeyError as exc:                                                            │
> │   378 │   │   │   raise ValueError(                                                              │
> │   379 │   │   │   │   f"Failed to find the pipeline named '{name}'. "                            │
> │                                                                                                  │
> │ ╭────────────────────────────────────────── locals ──────────────────────────────────────────╮   │
> │ │       context = <kedro.framework.context.context.KedroContext object at 0x7f8c907dc2e0>    │   │
> │ │  extra_params = {}                                                                         │   │
> │ │   from_inputs = []                                                                         │   │
> │ │    from_nodes = []                                                                         │   │
> │ │ load_versions = {}                                                                         │   │
> │ │          name = '__default__'                                                              │   │
> │ │     namespace = None                                                                       │   │
> │ │    node_names = ()                                                                         │   │
> │ │ pipeline_name = None                                                                       │   │
> │ │        runner = <kedro.runner.sequential_runner.SequentialRunner object at 0x7f8c907dc1c0> │   │
> │ │  save_version = '2023-06-27T14.44.06.340Z'                                                 │   │
> │ │          self = <kedro.framework.session.session.KedroSession object at 0x7f8c90dfc5e0>    │   │
> │ │    session_id = '2023-06-27T14.44.06.340Z'                                                 │   │
> │ │          tags = ()                                                                         │   │
> │ │      to_nodes = []                                                                         │   │
> │ │    to_outputs = []                                                                         │   │
> │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯   │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/framework/project/__init__.py:136 in inner                │
> │                                                                                                  │
> │   133 │                                                                                          │
> │   134 │   # pylint: disable=protected-access                                                     │
> │   135 │   def inner(self, *args, **kwargs):                                                      │
> │ ❱ 136 │   │   self._load_data()                                                                  │
> │   137 │   │   return func(self._content, *args, **kwargs)                                        │
> │   138 │                                                                                          │
> │   139 │   return inner                                                                           │
> │                                                                                                  │
> │ ╭─────────────────────────── locals ────────────────────────────╮                                │
> │ │   args = ('__default__',)                                     │                                │
> │ │   func = <built-in function getitem>                          │                                │
> │ │ kwargs = {}                                                   │                                │
> │ │   self = <repr-error "'int' object has no attribute 'split'"> │                                │
> │ ╰───────────────────────────────────────────────────────────────╯                                │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/framework/project/__init__.py:181 in _load_data           │
> │                                                                                                  │
> │   178 │   │   register_pipelines = self._get_pipelines_registry_callable(                        │
> │   179 │   │   │   self._pipelines_module                                                         │
> │   180 │   │   )                                                                                  │
> │ ❱ 181 │   │   project_pipelines = register_pipelines()                                           │
> │   182 │   │                                                                                      │
> │   183 │   │   self._content = project_pipelines                                                  │
> │   184 │   │   self._is_data_loaded = True                                                        │
> │                                                                                                  │
> │ ╭───────────────────────────────── locals ──────────────────────────────────╮                    │
> │ │ register_pipelines = <function register_pipelines at 0x7f8cd0879af0>      │                    │
> │ │               self = <repr-error "'int' object has no attribute 'split'"> │                    │
> │ ╰───────────────────────────────────────────────────────────────────────────╯                    │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/richlog/src/richlog/pipeline_registry.py:14 in                  │
> │ register_pipelines                                                                               │
> │                                                                                                  │
> │   11 │   Returns:                                                                                │
> │   12 │   │   A mapping from pipeline names to ``Pipeline`` objects.                              │
> │   13 │   """                                                                                     │
> │ ❱ 14 │   pipelines = find_pipelines()                                                            │
> │   15 │   pipelines["__default__"] = sum(pipelines.values())                                      │
> │   16 │   return pipelines                                                                        │
> │   17                                                                                             │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/framework/project/__init__.py:336 in find_pipelines       │
> │                                                                                                  │
> │   333 │   │   │   │   )                                                                          │
> │   334 │   │   │   )                                                                              │
> │   335 │   else:                                                                                  │
> │ ❱ 336 │   │   pipeline_obj = _create_pipeline(pipeline_module)                                   │
> │   337 │                                                                                          │
> │   338 │   pipelines_dict = {"__default__": pipeline_obj or pipeline([])}                         │
> │   339                                                                                            │
> │                                                                                                  │
> │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
> │ │      pipeline_module = <module 'richlog.pipeline' from                                       │ │
> │ │                        '/Users/Nok_Lam_Chan/GitHub/kedro/richlog/src/richlog/pipeline.py'>   │ │
> │ │ pipeline_module_name = 'richlog.pipeline'                                                    │ │
> │ │         pipeline_obj = None                                                                  │ │
> │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/framework/project/__init__.py:288 in _create_pipeline     │
> │                                                                                                  │
> │   285 │   │   )                                                                                  │
> │   286 │   │   return None                                                                        │
> │   287 │                                                                                          │
> │ ❱ 288 │   obj = getattr(pipeline_module, "create_pipeline")()                                    │
> │   289 │   if not isinstance(obj, Pipeline):                                                      │
> │   290 │   │   warnings.warn(                                                                     │
> │   291 │   │   │   f"Expected the 'create_pipeline' function in the "                             │
> │                                                                                                  │
> │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
> │ │ pipeline_module = <module 'richlog.pipeline' from                                            │ │
> │ │                   '/Users/Nok_Lam_Chan/GitHub/kedro/richlog/src/richlog/pipeline.py'>        │ │
> │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/richlog/src/richlog/pipeline.py:12 in create_pipeline           │
> │                                                                                                  │
> │    9                                                                                             │
> │   10                                                                                             │
> │   11 def create_pipeline(**kwargs) -> Pipeline:                                                  │
> │ ❱ 12 │   return pipeline(                                                                        │
> │   13 │   │   [                                                                                   │
> │   14 │   │   │   node(                                                                           │
> │   15 │   │   │   │   func=split_data,                                                            │
> │                                                                                                  │
> │ ╭── locals ───╮                                                                                  │
> │ │ kwargs = {} │                                                                                  │
> │ ╰─────────────╯                                                                                  │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/pipeline/modular_pipeline.py:210 in pipeline              │
> │                                                                                                  │
> │   207 │   │   # To ensure that we are always dealing with a *copy* of pipe.                      │
> │   208 │   │   pipe = Pipeline([pipe], tags=tags)                                                 │
> │   209 │   else:                                                                                  │
> │ ❱ 210 │   │   pipe = Pipeline(pipe, tags=tags)                                                   │
> │   211 │                                                                                          │
> │   212 │   if not any([inputs, outputs, parameters, namespace]):                                  │
> │   213 │   │   return pipe                                                                        │
> │                                                                                                  │
> │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
> │ │     inputs = None                                                                            │ │
> │ │  namespace = None                                                                            │ │
> │ │    outputs = None                                                                            │ │
> │ │ parameters = None                                                                            │ │
> │ │       pipe = [                                                                               │ │
> │ │              │   Node(split_data, ['example_iris_data', 'parameters'], {'X_train': 1},       │ │
> │ │              'split'),                                                                       │ │
> │ │              │   Node(make_predictions, ['X_train', 'X_test', 'y_train'], 'y_pred',          │ │
> │ │              'make_predictions'),                                                            │ │
> │ │              │   Node(report_accuracy, ['y_pred', 'y_test'], None, 'report_accuracy')        │ │
> │ │              ]                                                                               │ │
> │ │       tags = None                                                                            │ │
> │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/pipeline/pipeline.py:145 in __init__                      │
> │                                                                                                  │
> │   142 │   │   │   │   [[n] if isinstance(n, Node) else n.nodes for n in nodes]                   │
> │   143 │   │   │   )                                                                              │
> │   144 │   │   )                                                                                  │
> │ ❱ 145 │   │   _validate_transcoded_inputs_outputs(nodes)                                         │
> │   146 │   │   _tags = set(_to_list(tags))                                                        │
> │   147 │   │                                                                                      │
> │   148 │   │   nodes = [n.tag(_tags) for n in nodes]                                              │
> │                                                                                                  │
> │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
> │ │ nodes = [                                                                                    │ │
> │ │         │   Node(split_data, ['example_iris_data', 'parameters'], {'X_train': 1}, 'split'),  │ │
> │ │         │   Node(make_predictions, ['X_train', 'X_test', 'y_train'], 'y_pred',               │ │
> │ │         'make_predictions'),                                                                 │ │
> │ │         │   Node(report_accuracy, ['y_pred', 'y_test'], None, 'report_accuracy')             │ │
> │ │         ]                                                                                    │ │
> │ │  self = <repr-error "'Pipeline' object has no attribute '_topo_sorted_nodes'">               │ │
> │ │  tags = None                                                                                 │ │
> │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/pipeline/pipeline.py:875 in                               │
> │ _validate_transcoded_inputs_outputs                                                              │
> │                                                                                                  │
> │   872 │                                                                                          │
> │   873 │   invalid = set()                                                                        │
> │   874 │   for dataset_name in all_inputs_outputs:                                                │
> │ ❱ 875 │   │   name = _strip_transcoding(dataset_name)                                            │
> │   876 │   │   if name != dataset_name and name in all_inputs_outputs:                            │
> │   877 │   │   │   invalid.add(name)                                                              │
> │   878                                                                                            │
> │                                                                                                  │
> │ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
> │ │ all_inputs_outputs = {                                                                       │ │
> │ │                      │   1,                                                                  │ │
> │ │                      │   'X_test',                                                           │ │
> │ │                      │   'X_train',                                                          │ │
> │ │                      │   'example_iris_data',                                                │ │
> │ │                      │   'parameters',                                                       │ │
> │ │                      │   'y_test',                                                           │ │
> │ │                      │   'y_pred',                                                           │ │
> │ │                      │   'y_train'                                                           │ │
> │ │                      }                                                                       │ │
> │ │       dataset_name = 1                                                                       │ │
> │ │            invalid = set()                                                                   │ │
> │ │              nodes = [                                                                       │ │
> │ │                      │   Node(split_data, ['example_iris_data', 'parameters'], {'X_train':   │ │
> │ │                      1}, 'split'),                                                           │ │
> │ │                      │   Node(make_predictions, ['X_train', 'X_test', 'y_train'], 'y_pred',  │ │
> │ │                      'make_predictions'),                                                    │ │
> │ │                      │   Node(report_accuracy, ['y_pred', 'y_test'], None,                   │ │
> │ │                      'report_accuracy')                                                      │ │
> │ │                      ]                                                                       │ │
> │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/pipeline/pipeline.py:55 in _strip_transcoding             │
> │                                                                                                  │
> │    52 │   │   ValueError: Raised if more than one transcoding separator                          │
> │    53 │   │   is present in the name.                                                            │
> │    54 │   """                                                                                    │
> │ ❱  55 │   return _transcode_split(element)[0]                                                    │
> │    56                                                                                            │
> │    57                                                                                            │
> │    58 class OutputNotUniqueError(Exception):                                                     │
> │                                                                                                  │
> │ ╭── locals ───╮                                                                                  │
> │ │ element = 1 │                                                                                  │
> │ ╰─────────────╯                                                                                  │
> │                                                                                                  │
> │ /Users/Nok_Lam_Chan/GitHub/kedro/kedro/pipeline/pipeline.py:33 in _transcode_split               │
> │                                                                                                  │
> │    30 │   │   ValueError: Raised if more than one transcoding separator                          │
> │    31 │   │   is present in the name.                                                            │
> │    32 │   """                                                                                    │
> │ ❱  33 │   split_name = element.split(TRANSCODING_SEPARATOR)                                      │
> │    34 │                                                                                          │
> │    35 │   if len(split_name) > 2:                                                                │
> │    36 │   │   raise ValueError(                                                                  │
> │                                                                                                  │
> │ ╭── locals ───╮                                                                                  │
> │ │ element = 1 │                                                                                  │
> │ ╰─────────────╯                                                                                  │
> ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
> AttributeError: 'int' object has no attribute 'split'
```

</details>
</summary>

## Context
Why is this change important to you? How would you use it? How can it benefit other users?
The error is common for beginner. It would be great that if the error message can suggest the fix immediately.


## Possible Implementation
(Optional) Suggest an idea for implementing the addition or change.
Raise a KedroError instead of AttributeError

## Possible Alternatives
(Optional) Describe any alternative solutions or features you've considered.
Improve the logic how `dataset` is reference, insert validating logic.  The error is now coming from pipeline/pipeline.py:33 `_transcode_split`, which doesn't seem to be the right place to raise error.

Discussion:

Patch:
diff --git a/RELEASE.md b/RELEASE.md
index b13003c7..d8d40e7c 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -1,9 +1,10 @@
 # Upcoming Release 0.19.4
 
 ## Major features and improvements
+* Improved error message when passing wrong value to node.
 * Cookiecutter errors are shown in short format without the `--verbose` flag.
 * Kedro commands now work from any subdirectory within a Kedro project.
-* Kedro CLI now provides a better error message when project commands are run outside of a project i.e. `kedro run`
+* Kedro CLI now provides a better error message when project commands are run outside of a project i.e. `kedro run`.
 
 ## Bug fixes and other changes
 * Updated `kedro pipeline create` and `kedro pipeline delete` to read the base environment from the project settings.
diff --git a/kedro/pipeline/node.py b/kedro/pipeline/node.py
index 32baaf8e..ba0d43cd 100644
--- a/kedro/pipeline/node.py
+++ b/kedro/pipeline/node.py
@@ -42,7 +42,7 @@ class Node:
                 function. When dict[str, str] is provided, variable names
                 will be mapped to function argument names.
             outputs: The name or the list of the names of variables used
-                as outputs to the function. The number of names should match
+                as outputs of the function. The number of names should match
                 the number of outputs returned by the provided function.
                 When dict[str, str] is provided, variable names will be mapped
                 to the named outputs the function returns.
@@ -67,7 +67,6 @@ class Node:
                 and/or fullstops.
 
         """
-
         if not callable(func):
             raise ValueError(
                 _node_error_message(
@@ -83,6 +82,16 @@ class Node:
                 )
             )
 
+        for _input in _to_list(inputs):
+            if not isinstance(_input, str):
+                raise ValueError(
+                    _node_error_message(
+                        f"names of variables used as inputs to the function "
+                        f"must be of 'String' type, but {_input} from {inputs} "
+                        f"is '{type(_input)}'."
+                    )
+                )
+
         if outputs and not isinstance(outputs, (list, dict, str)):
             raise ValueError(
                 _node_error_message(
@@ -91,6 +100,16 @@ class Node:
                 )
             )
 
+        for _output in _to_list(outputs):
+            if not isinstance(_output, str):
+                raise ValueError(
+                    _node_error_message(
+                        f"names of variables used as outputs of the function "
+                        f"must be of 'String' type, but {_output} from {outputs} "
+                        f"is '{type(_output)}'."
+                    )
+                )
+
         if not inputs and not outputs:
             raise ValueError(
                 _node_error_message("it must have some 'inputs' or 'outputs'.")


Test patch:
diff --git a/tests/ipython/conftest.py b/tests/ipython/conftest.py
index edc7dbc9..f2636027 100644
--- a/tests/ipython/conftest.py
+++ b/tests/ipython/conftest.py
@@ -111,7 +111,7 @@ def dummy_node_empty_input():
     return node(
         func=dummy_function,
         inputs=["", ""],
-        outputs=[None],
+        outputs=None,
         name="dummy_node_empty_input",
     )
 
diff --git a/tests/pipeline/test_node.py b/tests/pipeline/test_node.py
index ae68dff8..3dcf3db7 100644
--- a/tests/pipeline/test_node.py
+++ b/tests/pipeline/test_node.py
@@ -252,6 +252,14 @@ def duplicate_output_list_node():
     return identity, "A", ["A", "A"]
 
 
+def bad_input_variable_name():
+    return lambda x: None, {"a": 1, "b": "B"}, {"a": "A", "b": "B"}
+
+
+def bad_output_variable_name():
+    return lambda x: None, {"a": "A", "b": "B"}, {"a": "A", "b": 2}
+
+
 @pytest.mark.parametrize(
     "func, expected",
     [
@@ -275,6 +283,11 @@ def duplicate_output_list_node():
             r"\(\[A\]\) -> \[A;A\] due to "
             r"duplicate output\(s\) {\'A\'}.",
         ),
+        (bad_input_variable_name, "names of variables used as inputs to the function "),
+        (
+            bad_output_variable_name,
+            "names of variables used as outputs of the function ",
+        ),
     ],
 )
 def test_bad_node(func, expected):