Describe the bug
In 2.5.24, FieldExtension#after_resolve was changed from:
def after_resolve(object:, arguments:, context:, value:, memo:)
value
end
to:
def after_resolve(object: nil, objects: nil, arguments:, context:, values: nil, value: nil, memo:)
value || values
end
The || operator treats false as falsy, so when a field resolver returns false, the base after_resolve evaluates false || nil → nil. This causes all Boolean fields returning false to silently become null in the response when any field extension is present (even one that doesn't override after_resolve).
Versions
graphql version: 2.5.24 (works on 2.5.23)
rails: 8.1.3
graphql-batch: 0.6.1
graphql-pro: 1.29.14
GraphQL schema
class MyExtension < GraphQL::Schema::FieldExtension
def resolve(object:, arguments:, **_rest)
# does something, doesn't override after_resolve
yield(object, arguments)
end
end
class BaseQuery < GraphQL::Schema::Resolver
extension MyExtension
end
class IsEmptyQuery < BaseQuery
argument :id, ID, required: true
type Boolean, null: false
def resolve(id:)
record = find_record(id)
record.children.empty? # can return false
end
end
class QueryType < GraphQL::Schema::Object
field :is_empty, resolver: IsEmptyQuery
end
class MySchema < GraphQL::Schema
query QueryType
end
GraphQL query
query($id: ID!) {
isEmpty(id: $id)
}
Expected response when the record has children:
{
"data": {
"isEmpty": false
}
}
Actual response:
{
"data": {
"isEmpty": null
}
}
Steps to reproduce
- Have any FieldExtension on a field (even one that doesn't override after_resolve)
- The field resolver returns false
- The Interpreter calls ext.after_resolve(value: false, ...)
- The base after_resolve evaluates false || nil → returns nil
Expected behavior
after_resolve should return false when value: false is passed
Actual behavior
after_resolve returns nil because false || values evaluates to values (which is nil).
Additional context
The fix should use nil-checking instead of ||:
def after_resolve(object: nil, objects: nil, arguments:, context:, values: nil, value: nil, memo:)
value.nil? ? values : value
end
This was introduced in the merge of resolve / resolve_next and after_resolve / after_resolve_next into unified methods with optional keyword arguments. The old after_resolve took value: as required and simply returned it, so false was never lost.
Describe the bug
In 2.5.24, FieldExtension#after_resolve was changed from:
to:
The || operator treats false as falsy, so when a field resolver returns false, the base after_resolve evaluates false || nil → nil. This causes all Boolean fields returning false to silently become null in the response when any field extension is present (even one that doesn't override after_resolve).
Versions
graphql version: 2.5.24 (works on 2.5.23)
rails: 8.1.3
graphql-batch: 0.6.1
graphql-pro: 1.29.14
GraphQL schema
GraphQL query
Expected response when the record has children:
Actual response:
Steps to reproduce
Expected behavior
after_resolve should return false when value: false is passed
Actual behavior
after_resolve returns nil because false || values evaluates to values (which is nil).
Additional context
The fix should use nil-checking instead of ||:
This was introduced in the merge of resolve / resolve_next and after_resolve / after_resolve_next into unified methods with optional keyword arguments. The old after_resolve took value: as required and simply returned it, so false was never lost.