In graphql-java, I'm overriding getExtensions on a GraphQLError, in order to pass a "code" extension for Apollo Client to consume.
When I added a breakpoint, I can see that GraphQLObjectMapper sees the error in the executionResult with all its fields, including extensions properly set as expected.
However, when the error arrives at apollo, it gets strangely morphed and the entire error object (including the extensions array) appears to be stuffed into the string message field like so:
{
"errors": [
{
"message": "Unexpected error value: { message: \"Exception while fetching data (/myQuery) : Didn't work\", locations: [[Object]], path: [\"myQuery\"], extensions: { code: \"MY_CODE\", classification: \"DataFetchingException\" } }",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"mailLabels"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR"
}
}
],
"data": null
}
As far as I can tell apollo is not doing anything wrong. My suspicion is that graphql-java may be the one stuffing this entire error into the "message" field" and then setting the code as "INTERNAL_SERVER_ERROR", but I'm not really sure. Is there something I can do on the graphql-java end to prevent this and make it properly pass the extensions and not stuff them into the message value? Any assistance would be appreciated.
It is not caused by graphql-java
but graphql-java-servlet
. In some old version , by default it does not serialize GraphQLError
to the structure defined by the GraphQL specification , which should be fixed in 7.5.1 in this issue.
If you cannot upgrade to the latest version , the simplest way is customize GraphQLObjectMapper
and overriding its convertSanitizedExecutionResult
:
public class CustomObjectMapper extends GraphQLObjectMapper {
@Override
public Map<String, Object> convertSanitizedExecutionResult(ExecutionResult executionResult, boolean includeData) {
Map<String, Object> result = super.convertSanitizedExecutionResult(executionResult, includeData);
if(result.containsKey("errors")){
result.put("errors", executionResult.getErrors().stream().map(err->err.toSpecification()).collect(toList()));
}
}
}