Skip to content

Commit f8ed6d1

Browse files
authored
Merge pull request #5301 from fisxoj/mn-nullable-array-element-type-errors
Improve nullable array element type error reporting
2 parents 6f8a205 + bf75b19 commit f8ed6d1

File tree

5 files changed

+33
-7
lines changed

5 files changed

+33
-7
lines changed

lib/graphql/execution/interpreter/runtime.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,9 +475,10 @@ def continue_value(value, field, is_non_null, ast_node, result_name, selection_r
475475
if is_non_null
476476
set_result(selection_result, result_name, nil, false, is_non_null) do
477477
# When this comes from a list item, use the parent object:
478-
parent_type = selection_result.is_a?(GraphQLResultArray) ? selection_result.graphql_parent.graphql_result_type : selection_result.graphql_result_type
478+
is_from_array = selection_result.is_a?(GraphQLResultArray)
479+
parent_type = is_from_array ? selection_result.graphql_parent.graphql_result_type : selection_result.graphql_result_type
479480
# This block is called if `result_name` is not dead. (Maybe a previous invalid nil caused it be marked dead.)
480-
err = parent_type::InvalidNullError.new(parent_type, field, ast_node)
481+
err = parent_type::InvalidNullError.new(parent_type, field, ast_node, is_from_array: is_from_array)
481482
schema.type_error(err, context)
482483
end
483484
else

lib/graphql/invalid_null_error.rb

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,24 @@ class InvalidNullError < GraphQL::Error
1212
# @return [GraphQL::Language::Nodes::Field] the field where the error occurred
1313
attr_reader :ast_node
1414

15-
def initialize(parent_type, field, ast_node)
15+
# @return [Boolean] indicates an array result caused the error
16+
attr_reader :is_from_array
17+
18+
def initialize(parent_type, field, ast_node, is_from_array: false)
1619
@parent_type = parent_type
1720
@field = field
1821
@ast_node = ast_node
19-
super("Cannot return null for non-nullable field #{@parent_type.graphql_name}.#{@field.graphql_name}")
22+
@is_from_array = is_from_array
23+
24+
# For List elements, identify the non-null error is for an
25+
# element and the required element type so it's not ambiguous
26+
# whether it was caused by a null instead of the list or a
27+
# null element.
28+
if @is_from_array
29+
super("Cannot return null for non-nullable element of type '#{@field.type.of_type.of_type.to_type_signature}' for #{@parent_type.graphql_name}.#{@field.graphql_name}")
30+
else
31+
super("Cannot return null for non-nullable field #{@parent_type.graphql_name}.#{@field.graphql_name}")
32+
end
2033
end
2134

2235
class << self

spec/graphql/execution/errors_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ def non_nullable_array
307307
it "outputs the appropriate error message when using non-interpreter schema" do
308308
res = ErrorsTestSchemaWithoutInterpreter.execute("{ nonNullableArray }")
309309
expected_error = {
310-
"message" => "Cannot return null for non-nullable field Query.nonNullableArray",
310+
"message" => "Cannot return null for non-nullable element of type 'String!' for Query.nonNullableArray",
311311
"path" => ["nonNullableArray", 0],
312312
"locations" => [{ "line" => 1, "column" => 3 }]
313313
}
@@ -317,7 +317,7 @@ def non_nullable_array
317317
it "outputs the appropriate error message when using interpreter schema" do
318318
res = ErrorsTestSchema.execute("{ nonNullableArray }")
319319
expected_error = {
320-
"message" => "Cannot return null for non-nullable field Query.nonNullableArray",
320+
"message" => "Cannot return null for non-nullable element of type 'String!' for Query.nonNullableArray",
321321
"path" => ["nonNullableArray", 0],
322322
"locations" => [{ "line" => 1, "column" => 3 }]
323323
}

spec/graphql/execution/interpreter_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ def execute_multiplex(multiplex:)
501501
}
502502
}
503503
GRAPHQL
504-
assert_equal ["Cannot return null for non-nullable field Query.find"], res["errors"].map { |e| e["message"] }
504+
assert_equal ["Cannot return null for non-nullable element of type 'Entity!' for Query.find"], res["errors"].map { |e| e["message"] }
505505
end
506506

507507
it "works with lists of unions" do

spec/graphql/schema/list_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ def echoes(items:)
116116
def nil_echoes(items:)
117117
items.first[:items]
118118
end
119+
120+
field :invalid_result, [String], null: false
121+
122+
def invalid_result
123+
["A", "B", nil]
124+
end
119125
end
120126

121127
query(Query)
@@ -127,6 +133,12 @@ def nil_echoes(items:)
127133
assert_equal [expected_error], res["errors"].map { |e| e["message"] }
128134
end
129135

136+
it "reports when an element must be non-nil" do
137+
res = ListValidationSchema.execute "{ invalidResult }"
138+
expected_error = "Cannot return null for non-nullable element of type 'String!' for Query.invalidResult"
139+
assert_equal [expected_error], res["errors"].map { |e| e["message"] }
140+
end
141+
130142
it "works with #valid_input?" do
131143
assert ListValidationSchema::Item.to_list_type.valid_isolated_input?(["A", "B"])
132144
refute ListValidationSchema::Item.to_list_type.valid_isolated_input?(["A", "B", "C"])

0 commit comments

Comments
 (0)