Skip to content

Update Int and Float coercion logic to be spec compliant #5306

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

swalkinshaw
Copy link
Collaborator

The spec says that scalars should return query/field errors when input or result coercion values don't conform to the spec.

Int example: https://spec.graphql.org/draft/#sel-GAHXRFHCAACGS6rU

This updates the logic to return GraphQL::CoercionError (execution errors) instead of raised RuntimeErrors which would not result in a client error by default.

The logic and error messages are were taken from the graphql-js scalar implementation.
Note that this is likely a breaking change for schema developers. For clients, it's an improvement since they might get some sort of "internal server error" otherwise.

@rmosolgo I didn't update all the necessary specs yet because I figured this would need some further discussion. It's a fairly large behaviour change from the schema's perspective but ultimately we should try to support this to be spec compliant.

The spec says that scalars should return query/field errors when input
or result coercion values don't conform to the spec.

This updates the lgoic to return `GraphQL::CoercionError` (execution
errors) instead of raised `RuntimeError`s which would not result in a
client error by default.

The logic and error messages are were taken from graphql-js.

Note that this is likely a breaking change for schema developers. For
clients, it's an improvement since they might get some sort of "internal
srever error" otherwise.
@rmosolgo
Copy link
Owner

I'm definitely interested in complying with the spec by default eventually, but I think that before changing the defaults, we should release a version with warnings that the default behavior is going to change with a link to the docs about how to either override the defaults (to retain current behavior without the warning) or opt into the future default behavior.

The other thing is to make sure these still show up in peoples' bug trackers. The intention behind raising errors was to make sure developers become aware that their data and schema don't match -- something needs to be fixed on the backend. What would have to happen to make sure these CoercionErrors show up to developers?

@swalkinshaw
Copy link
Collaborator Author

Yeah that's the hard part because the gem has no abstraction for error "reporting". I think the best we can do is a hybrid approach:

  1. call the type_error hook with an instantiated exception
  2. add an empty branch to the default type_error implementation for a no-op
  3. return the execution error

Then at least this gives people a place to implement the behaviour they want but it's still opt-in and a "breaking change".

Unless I'm missing something, there's no way to both report an exception and return an execution error currently. This gem would have to check for various bug tracker integrations.

With the Railtie we could default to using Rails.error.report but that still assumes that the application is actually using that newer interface.

So it's a catch 22 where I don't think it's possible to get the ideal behaviour. We need to raise an exception... but also not raise one.

@rmosolgo
Copy link
Owner

rmosolgo commented Apr 1, 2025

What if we preserve the current default behavior, but also:

  • Add a new configuration, eg MySchema.raise_scalar_type_errors = nil
  • In the default type_error behavior:
    • if that configuration wasn't set to true, warn that the default behavior is changing in a future version and that the new setting should be assigned to either true or else custom handling should be put in def self.type_error to preserve the current behavior in future versions
    • if the configuration is set to true, do the new behavior (without any warning)

Then, in a future version, we change the default to return errors and deprecate the now-useless config. That would move us progressively toward spec compliance while warning people about what's going on. What do you think?

abstraction for error "reporting"

That's cool, I didn't know Rails had Rails.errors.report(err). I wonder if GraphQL-Ruby could hand errors off to that somehow 🤔

@swalkinshaw
Copy link
Collaborator Author

MySchema.raise_scalar_type_errors sounds good 👍 If you want to prioritize feel free. Otherwise I'll try over the next week or two

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 this pull request may close these issues.

2 participants