- Published on
- • 2 min read
GraphQL ruby error handling
- Authors

- Name
- Shaiju Edakulangara
- @eshaiju
In GraphQL, we can expose errors as part of our response. Clients should check the errors field in the result. For instance, querying a non-existent field returns a system error:
{
"errors": [
{
"message": "Field 'user' doesn't exist on type 'Article'",
"locations": [{ "line": 5, "column": 5 }]
}
]
}
User-Friendly Errors
For validation failures, we often want to expose errors directly on our types:
# app/graphql/types/article_type.rb
ArticleType = GraphQL::ObjectType.define do
name "Article"
field :title, types.String
field :errors, types[types.String] do
resolve -> (obj, args, ctx) { obj.errors.full_messages }
end
end
Clients can then check these errors after a mutation:
mutation {
createArticle(article: { title: "" }) {
id
errors
}
}
Raising Execution Errors
If a resolver needs to report an error that should go into the top-level errors array, return a GraphQL::ExecutionError:
# app/graphql/mutations/article_mutations.rb
resolve -> (obj, args, ctx) {
begin
Article.create!(args["article"].to_h)
rescue ActiveRecord::RecordInvalid => err
GraphQL::ExecutionError.new("Invalid input: #{err.record.errors.full_messages.join(', ')}")
end
}
DRY Error Handling with Resolvers
Instead of begin...rescue in every field, you can wrap resolvers:
# app/graphql/resolvers/rescue_from.rb
class RescueFrom
def initialize(error_superclass, resolve_func)
@error_superclass = error_superclass
@resolve_func = resolve_func
end
def call(obj, args, ctx)
@resolve_func.call(obj, args, ctx)
rescue @error_superclass => err
GraphQL::ExecutionError.new(err.message)
end
end
Apply it to your fields:
# app/graphql/mutations/article_mutations.rb
field :create_article, ArticleType do
resolve RescueFrom.new(ActiveRecord::RecordInvalid, -> (obj, args, ctx) { ... })
end
Reference: GraphQL Ruby Documentation