diff --git a/src/graphql/utilities/coerce_input_value.py b/src/graphql/utilities/coerce_input_value.py index 31237d1e..6017769c 100644 --- a/src/graphql/utilities/coerce_input_value.py +++ b/src/graphql/utilities/coerce_input_value.py @@ -70,7 +70,19 @@ def coerce_input_value( if is_iterable(input_value): coerced_list: List[Any] = [] append_item = coerced_list.append + is_nested_list = bool( + is_list_type(item_type) and len(tuple(input_value)) > 1 + ) for index, item_value in enumerate(input_value): + if is_nested_list and not is_iterable(item_value): + # Input values should be iterable for multivalued nested list type + on_error( + path.as_list() if path else Path(path, index, None).as_list(), + item_value, + GraphQLError( + f"Expected type '{inspect(item_type)}' to be a list." + ), + ) append_item( coerce_input_value( item_value, item_type, on_error, Path(path, index, None) diff --git a/tests/utilities/test_coerce_input_value.py b/tests/utilities/test_coerce_input_value.py index f34e8564..5b0155df 100644 --- a/tests/utilities/test_coerce_input_value.py +++ b/tests/utilities/test_coerce_input_value.py @@ -352,13 +352,24 @@ def returns_null_for_a_null_value(): result = _coerce_value(None, TestNestedList) assert expect_value(result) is None - def returns_nested_list_for_nested_non_list_values(): + def returns_error_for_nested_non_list_values(): result = _coerce_value([1, 2, 3], TestNestedList) - assert expect_value(result) == [[1], [2], [3]] + assert expect_errors(result) == [ + ("Expected type '[Int]' to be a list.", [0], 1), + ("Expected type '[Int]' to be a list.", [1], 2), + ("Expected type '[Int]' to be a list.", [2], 3), + ] def returns_nested_null_for_nested_null_values(): + result = _coerce_value([[None], [None]], TestNestedList) + assert expect_value(result) == [[None], [None]] + + def returns_errors_for_null_values(): result = _coerce_value([42, [None], None], TestNestedList) - assert expect_value(result) == [[42], [None], None] + assert expect_errors(result) == [ + ("Expected type '[Int]' to be a list.", [0], 42), + ("Expected type '[Int]' to be a list.", [2], None), + ] def describe_with_default_on_error(): def throw_error_without_path():