Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoMethodError - undefined method `keyword_arguments' for #<GraphQL::ExecutionError... #4074

Closed
arekk opened this issue May 24, 2022 · 4 comments · Fixed by #4079
Closed

NoMethodError - undefined method `keyword_arguments' for #<GraphQL::ExecutionError... #4074

arekk opened this issue May 24, 2022 · 4 comments · Fixed by #4079

Comments

@arekk
Copy link

arekk commented May 24, 2022

Describe the bug

When a resolver-specific complexity defined as Proc, raising a GraphQL::ExecutionError produce an exception instead of response.

Versions

graphql version: 1.13.12 but tested on 2.x and issue exists as well
rails (or other framework): 1.13.12

GraphQL schema

Sample resolver:

class ParcelsResolver < GraphQL::Schema::Resolver

  complexity ->(context, args, child_complexity) do
    if filter.present? && filter[:type] == 'id'
      child_complexity
    else
      args[:limit] * child_complexity
    end
  end
  
  # Filter is a input {type: [all, id], id: 123}
  argument :limit, Integer, required: false, default_value: 50
  argument :filter, Filter, required: false, default_value: { type: 'all' }, prepare: ->(*args) { prepare_filter(*args) }

  class << self
    def prepare_filter(filter, context)
      if filter.present? && filter[:type] == 'id' && filter[:id].blank?
        raise GraphQL::ExecutionError, 'filter.ID is missing' if filter[:id].blank?
      end
    end
  end

  # more code here

  def resolve(limit:, page:, filter:, sort: nil)
    ...
  end

end   

Steps to reproduce

Call a resolver with a query passing id as filtering criteria, but give no id:

{
  parcels(filter: {type: ID}) {
    ...
  }
}

Expected behavior

Get a standard error like

{
  "data": null,
  "errors": [
    {
      "message": "filter.ID is missing",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "parcels"
      ]
    }
  ]
}

Actual behavior

Exception "NoMethodError - undefined method `keyword_arguments' for #<GraphQL::ExecutionError:..." is thrown, without any specific backtrace.

Additional context

Some debugging points a problem in graphql-1.12.13/lib/graphql/analysis/ast/query_complexity.rb:56:

case defined_complexity
  when Proc
    arguments = @query.arguments_for(@node, @field_definition)
    defined_complexity.call(@query.context, arguments.keyword_arguments, child_complexity)

Seems to arguments be a GraphQL::ExecutionError instance, but GraphQL::ExecutionError has no method keyword_arguments

Workaround is to define own exception like:

class MyExecutionError < GraphQL::ExecutionError
  def keyword_arguments
    []
  end
end

and raise it instead of native GraphQL::ExecutionError.

@arekk
Copy link
Author

arekk commented May 27, 2022

Thank you @rmosolgo

@ravangen
Copy link
Contributor

👋 Would it be possible to have this fix back-ported to 1.13.x too? Looks like it was released in 2.0.9 only. We want to go to v2, but its taking some time to migrate our larger code base 😞 Thanks! ❤️

@rmosolgo
Copy link
Owner

Sure thing -- I just released it in 1.13.17 (via #4248)!

@ravangen
Copy link
Contributor

Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants