graphql-java
graphql-java copied to clipboard
Custom scalars validation message
We implemented a few custom scalars by extending the Coercing
interface. Validating input values is done in parseLiteral()
method implementation which returns T
value for a successful parsed value or throws a CoercingParseLiteralException
for invalid values. I expected the text message in the exception to be the error message for that exception to be the error message returned in the response, but instead it is ignored and a generic message is received. I'm getting:
input.name' with value 'StringValue{value='15.26.4.2/40'}' is not a valid 'IpAddress' @ 'myMutation'
instead of: 40 is not a valid IPv4 mask.
Custom scalars implementation doesn't allow custom error message for validation errors result. This code in graphql.validation.ValidationUtil
is where the custom message is lost:
private boolean parseLiteral(Value value, Coercing coercing) {
try {
return coercing.parseLiteral(value) != null;
} catch (CoercingParseLiteralException e) {
return false;
}
}
Maybe instead of a boolean
, a ValidationResult
object could be returned which would encapsulate the valid/invalid state as well as the error message.
Another option would be to change the I parseLiteral(Object input) throws CoercingParseLiteralException
signature to return an encapsulating result object that would represent the possible validation error in a type safe manner (similar in spirit to the Either
type) instead of using exceptions for that which is less explicit and more costly. That would also allow to use multiple error messages for the same scalar value. The validation I use potentially produces multiple messages which may produce a better UX.
I think the optimal error handling would be a combination of the API usage information that the scalar validation doesn't have (argument name, queryPath, scalar type) and the custom error message, but in an object form like so:
{
"errors": [
{
"message": "40 is not a valid IPv4 mask",
"field": "input",
"argument": "name",
"queryPath": "myMutation",
"extensions": {
"classification": "ValidationError"
}
}
]
}
That way the UI can make the best use of the available information like rendering the right message in the right context. Meshing it all into a single string means I either loose information that's valuable for API callers or I have to parse and clean the message for UI usage (or API users that prefer a clear take on what went wrong).
I can try to submit a PR if this is considered a desired change.
Hi, we've got the same problem. We implemented some custom scalars for validation. The frontend needs translation keys to display a user friendly error message.
Using the exception message would be a very good solution.
I was wondering: since CoercingParseLiteralException is already a GraphQLError, why is it not used to build the error message?
I was wondering: since CoercingParseLiteralException is already a GraphQLError, why is it not used to build the error message?
Its just over sight - no great reason. I think the idea of transferring the graphql error that comes outfrom a custom scalar is a great idea (extensions and all)