Hello community,
I'm reaching to this section as I have been working on several weeks to understand whether this is potentially a bug.
The piece of code below regards to a login mutation. It takes email and password, then ruby-graphql should return a token. The actual values for email and password are passed as variables.
mutation {
token: login(
email: "...",
password: "..."
)
}
In production environment GraphQL spills an odd error regarding mutations not being configured.
{
"errors": [
{
"message": "Schema is not configured for mutations",
"locations": [
{
"line": 1,
"column": 1
}
],
"path": [
"mutation"
],
"extensions": {
"code": "missingMutationConfiguration"
}
}
],
"extensions": {}
}
Any ideas?
Hey @cassiopagnoncelli I like to help but need more information about your schema setup. Specifically the call site where you have
class MySchema < GraphQL::Schema
# Required:
query Types::Query
# Optional:
mutation Types::Mutation
subscription Types::Subscription
end
And your equivalent of Types::MutationType class.
From the error, it looks like it might be broken right at the Schema def level.
@daemonsy Thank you so much, here it is the schema definition
require 'apollo/tracing'
class ApiSchema < GraphQL::Schema
max_depth 5
max_complexity 400
use GraphQL::Batch
use ApolloTracing.new
# use BatchLoader::GraphQL
# lazy_resolve BatchLoader, :sync
query(Types::QueryType)
mutation(Types::MutationType)
end
ApiSchema.middleware <<
GraphQL::Schema::TimeoutMiddleware.new(max_seconds: 5) do |err, query|
Rails.logger.info("GraphQL Timeout: #{query.query_string}")
end
For mutations, we have mutation_type.rb:
module Types
class MutationType < Types::BaseObject
field :login, mutation: Mutations::Login
field :recoverPassword, mutation: Mutations::UserRecoverPassword
# (...)
end
end
Maybe it might be useful adding base_mutation.rb itself as that might be part of the problem:
class Mutations::BaseMutation < GraphQL::Schema::RelayClassicMutation
# Add your custom classes if you have them:
# This is used for generating payload types
object_class Types::BaseObject
# This is used for return fields on the mutation's payload
field_class Types::BaseField
# This is used for generating the `input: { ... }` object type
input_object_class Types::BaseInputObject
end
I have no clue where the issue is. Any idea?
Hey @cassiopagnoncelli the mutation looks very standard to me.
I've bumped into cases where there was syntax error (or missing some required setup field) and it didn't throw a direct error (rather something XYZ constant is not loaded), not sure if it's something like that in your case.
I'm going try to reduce this to see if that's where the problem is. If you're actively on this, I suggest that maybe trying to comment out more optional things (such as apollo tracing, the middleware etc) to see one of those lines is part of the cause.
I think you probably cannot share your working code in Mutations::Login and Mutations::UserRecoverPassword.
Maybe instead I'll try to create a basic working setup of mutations on a demo (probably here) so you can change Ruby / GraphQL versions to see if that's the cause of your problem.
Hello @daemonsy
True, it actually works fine on dev environment so should be a typo. I tried removing everything from plugins to modules in a way to have Ruby-GraphQL as simple as possible, result is problem persists.
I have probably reviewed all configuration files (actually it's mostly a standard Rails 5.2.2 app) and can't find the issue. I'm giving my best to find where the issue is, but I can't find a hint where the problem might be. I'm probably working on this issue for a month :/
I'm trying to think what _could_ be different in development vs. production. One thing that stood out is parallelism -- are you using a multi-threaded or multiprocess server like Puma or Phusion Passenger? I wonder if a process could somehow fork _before_ the schema is _totally_ booted, and then the forked schema isn't all set up properly.
I don't really have a clear suggestion, except something that _sometimes_ helps with these loading issues. Try adding at the _very bottom_ of api_schema.rb:
# Ensure that the schema is booted eagerly, instead of before the first query
ApiSchema.graphql_definition
It might work 馃槄 . (Longer term, I'm trying to simplify schema boot over at #2363.)
Hi @rmosolgo
Great to see you in this discussion. Yes it's running behind Puma though it looks quite standard setup.
I tried that, it doesn't work, tried in other places too (like application.rb), error persists. To give more glimpse on this error, QueryType always loads alongside libs (batch and apollo), however MutationType is never loaded on production.
Overview is,
I'm wondering if it takes something special to have mutations working on prod?
馃槚 Sorry it didn't help!
something special to have mutations working on prod?
No, not that I know of! GraphQL-Ruby is about 4 years old and I'd imagine it has thousands of running instances, but I haven't heard of this issue until now 馃槚
Question, what does it says if you run the following ?
mutation {
login(email: "...",password: "...") {
token
}
}
It's actually the first time I've seen your syntax XD (as for why that would work on dev on not on prod is anyone's guess)
Hello @nekogami
It returns
{
"errors": [
{
"message": "Selections can't be made on scalars (field 'login' returns String but has selections [token])",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"mutation",
"login"
],
"extensions": {
"code": "selectionMismatch",
"nodeName": "field 'login'",
"typeName": "String"
}
}
],
"extensions": {}
}
Any idea on what the issue is?
Thank you so much!
From what I understand, in your returned object, token is not a string but an array, if so, you will have to change your selection value.
IE:
if object.token is an array of string, the token field inside the return type has to be declared as [String]
@nekogami No not really, turns out that the query and mutation are well-formed, it actually returns a value, look:
{
"data": {
"token": "eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7ImlkIjoxNjQ1MywibWVyY2hhbnRJZCI6MTE4NSwiZW1haWwiOiJub2VseXBpY29sbG9AZ21haWwuY29tIiwicGVybWlzc2lvbnMiOm51bGwsIm5hbWUiOiJOb2VseSBQaWNvbGxvIn0sImV4cCI6MTU2NzEzMTY3N30.DosoZV5f6_uRdERR9p5paRVjYBu5Fz3H137uslUGel8"
},
"extensions": {}
}
I just run it in my machine under Docker on development environment. When I deploy to production, mutations won't work. Types::QueryType is recognized and queries work perfectly, but not for Types::MutationType as they aren't even loaded.
hey @cassiopagnoncelli did you ever get to the root of the issue?
@daemonsy Not really, what I did was to actually recode from scratch and now it's up & running.
@cassiopagnoncelli sorry to hear that you have to redo the schema from scratch. Well at least the problem's gone :)
I'm going to close the issue, if you bump into some issue like this 馃 in the future and discover a gotcha, be glad to take a PR to document it.