Hi and thanks for the nice software. I've started ...
# graphql-kotlin
a
Hi and thanks for the nice software. I've started to randomly get an error when making requests from my cmp client (desktop apollo kotlin). The server throws an error, "Unknown operation named '<my operation name>'". I've tracked it down to graphql-java here: https://github.com/graphql-java/graphql-java/blob/5ce0eadb434848910cb417c646cfd30b8e75a72b/src/main/java/graphql/language/NodeUtil.java#L84 It will happen typically in the first few requests when starting the client. When I try again a second later it works and doesn't seem to happen again, so perhaps it's client related... The server is not restarted between and is always running. What could be causing that?
m
Would you have the full stack trace by any chance?
a
From the server? No, but I could probably produce one
m
If you can get a network dump, you should see what's being sent. Typically it's a POST request looking like so:
Copy code
{
  "operationName": "LaunchList",
  "variables": {
    "cursor": "1584533760"
  },
  "query": "query LaunchList($cursor: String){ ... }"
}
Looks like what is sent in
operationName
doesn't match what is sent in
query
TBH I'm not sure what could be causing that. Maybe a bad APQ cache if you're using APQ?
a
Yep, we are using a apq
Copy code
AutomaticPersistedQueriesProvider(DefaultAutomaticPersistedQueriesCache())
I will have a look at what the client sends after lunch and post it. Thanks!
👍 1
Sorry, can't reproduce it right now, but I'll let you know if it surfaces again.
👍 1
Well it finally happened again but it doesn't look like it's a problem with operationName vs query.
Copy code
{
  "operationName": "GetHeatPumpEnergySummary",
  "variables": {
    "giid": "254891327576"
  },
  "query": "query GetHeatPumpEnergySummary($giid: Giid!) { ... }"
}
There are 3 requests sent in the same millisecond by the client so I'm suspecting that's got to do with it. Only one of them failed, the others were successful.
Copy code
Error received: Error(message = Unknown operation named 'GetHeatPumpEnergySummary'., locations = null, path=null, extensions = null, nonStandardFields = null)
m
That does sound like a race condition indeed 🤔
a
It's a bit tough to reproduce, maybe I will have to write a stress tester. Looking at another failed example, the operations are coming in very closely in time,
Copy code
>>IN 2025-01-16T07:53:50.846788Z: {"operationName":"GetHeatPumpEnergyLastHour",...
>>IN 2025-01-16T07:53:50.846790Z: {"operationName":"GetHeatPumps",...
>>IN 2025-01-16T07:53:50.846788Z: {"operationName":"GetHeatPumpEnergySummary",...
I suppose it could be deserializer issue... I am using a jacksonObjectMapper() that is shared with all requests
Copy code
val rawRequest = request.call.receiveText()
val parsed = mapper.readValue(rawRequest, GraphQLServerRequest::class.java)
m
Oooo, that could be it!
a
Hmm after logging the parsed requests, they look fine, so I think that can be ruled out.
Made some progress. It's something with the APQ for sure
Screenshot 2025-01-16 at 11.13.43.png
m
Ah!
a
So... what could I be doing that's causing the APQ to fetch the wrong cached item??
m
That potentially sounds like a GraphQL java issue? Sorry, not super familiar with those parts
a
indeed
I don't think any APQ functionality is turned on in the client side
it's a SHA-256 hash. I'm not a mathematician, but that should be fairly unlikely to collide
m
Since your input seems to contain the full document, there might not even be hashes involved
a
It does store parsed and validated documents by cache, as far as I can see. However. This doesn't look entirely thread safe:
🎯 1
Boom... thats it 😄
m
Excellent find!
January 2nd! Living on the edge!
a
No it was last year, lol. Thats what I get for not updating
m
Damn right! I still live in 2024 😅