Description
When executing a query with validate: false, if a field referenced in the query no longer exists in the runtime schema (due to schema changes, visibility profiles, or runtime masking), the interpreter crashes with:
NoMethodError: undefined method 'dynamic_introspection' for nil
This happens in GraphQL::Execution::Interpreter::Runtime#evaluate_selection where query.types.field(owner_type, field_name) returns nil, and the code proceeds to call field_defn.dynamic_introspection without a nil check.
Steps to reproduce
- Create a schema with a field on a type
- Execute a query referencing that field with
validate: false
- Remove the field from the schema (or change its visibility so it is no longer visible at runtime)
- Execute the same query again with
validate: false
schema.execute(
"query { viewer { removedField } }",
validate: false
)
# => NoMethodError: undefined method 'dynamic_introspection' for nil
Expected behavior
When validate: false is used and a field cannot be resolved at runtime, the interpreter should return a structured GraphQL::ExecutionError (e.g., "Field 'removedField' on type 'User' could not be resolved") rather than raising an unhandled NoMethodError. The field result should be set to null and execution should continue for the remaining fields.
Context
There are legitimate use cases for validate: false -- for example, when validation has already been performed externally, or when using persisted queries where the query was validated at registration time. In these scenarios, a field can go missing between the time validation was performed and execution time. The current behavior produces an unhelpful error with no indication of which field or type caused the problem, making debugging difficult.
A nil check on field_defn in evaluate_selection before accessing dynamic_introspection would make this error path graceful and informative.
Description
When executing a query with
validate: false, if a field referenced in the query no longer exists in the runtime schema (due to schema changes, visibility profiles, or runtime masking), the interpreter crashes with:This happens in
GraphQL::Execution::Interpreter::Runtime#evaluate_selectionwherequery.types.field(owner_type, field_name)returnsnil, and the code proceeds to callfield_defn.dynamic_introspectionwithout a nil check.Steps to reproduce
validate: falsevalidate: falseExpected behavior
When
validate: falseis used and a field cannot be resolved at runtime, the interpreter should return a structuredGraphQL::ExecutionError(e.g.,"Field 'removedField' on type 'User' could not be resolved") rather than raising an unhandledNoMethodError. The field result should be set tonulland execution should continue for the remaining fields.Context
There are legitimate use cases for
validate: false-- for example, when validation has already been performed externally, or when using persisted queries where the query was validated at registration time. In these scenarios, a field can go missing between the time validation was performed and execution time. The current behavior produces an unhelpful error with no indication of which field or type caused the problem, making debugging difficult.A nil check on
field_defninevaluate_selectionbefore accessingdynamic_introspectionwould make this error path graceful and informative.