Skip to content

GraphQL error code pattern #5221

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
ravangen opened this issue Feb 4, 2025 · 1 comment
Open

GraphQL error code pattern #5221

ravangen opened this issue Feb 4, 2025 · 1 comment

Comments

@ravangen
Copy link
Contributor

ravangen commented Feb 4, 2025

Is your feature request related to a problem? Please describe.

Request for guidance around GraphQL error's extensions.code (spec example). For static validation, the different errors have a camelCase value. Other errors like ParseError and more broadly ExecutionError usages don't make any attempt to provide a code.

We're looking to expand usage of the concept of an error code more broadly to have a more reliable way to group errors together, and was wondering about how this gem was thinking about classifying different types of errors.

Example

def code
"argumentLiteralsIncompatible"
end

it "makes a nice validation error" do
result = CoercionErrorSchema.execute("{ f1(arg: \"a\") }")
expected_error = {
"message" => "\"a\" can't be Custom value",
"locations" => [{"line"=>1, "column"=>3}],
"path" => ["query", "f1", "arg"],
"extensions" => {
"code"=>"argumentLiteralsIncompatible",
"typeName"=>"CoercionError"
}
}
assert_equal [expected_error], result["errors"]
end

Describe the solution you'd like

Discuss the notion of an error code for gem related functionality and its format.

Easier to reliably have content added to extensions.

Contextual

There are some cases like raise GraphQL::CoercionError where having additional runtime information would help. This error can be raised by user input (client) and persisted data (server). Having an awareness of which scenario is resulting in this exception would help attribute who is responsible for fixing this invalid state. Essentially allowing us to distinguish between HTTP 400 bad input and 500 bad response.

Describe alternatives you've considered

I acknowledge ExecutionError accepts extensions, where code can be provided. But for cases where gem code raises such an exception (e.g. CoercionError), it is annoying to patch / inject a code later on via custom processing.

Additional context

We (Shopify) already have custom codes that predate the static validation ones in CONSTANT_CASE (e.g. TIMEOUT, THROTTLED, INTERNAL_SERVER_ERROR), but we can deal with different formats if need be.

@rmosolgo
Copy link
Owner

rmosolgo commented Feb 5, 2025

Hey, great question. Honestly, extensions.code in this library is totally ad-hoc. The example you linked was added when we needed more context on errors in GitHub, but before the linked spec existed IIRC.

I'm open to totally overhauling the existing extensions situation because it was never really spec'd or documented and because a better system could easily support backwards compat if anyone actually wanted it. (Somewhat related: #4308, #4711) And I can see how GraphQL-Ruby's own error-raising behavior will need to be improved to support better error codes.

I found some of Shopify's GraphQL error codes here: https://shopify.dev/docs/api/admin-graphql#status_and_error_codes Is there another doc that lists the full set? I'd like to wrap my head around them before diving in.

Please feel free to open up PRs in this direction if you have anything in mind already. Thanks again for the suggestion.

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

No branches or pull requests

2 participants