I’m looking into some sort of a graceful way of tr...
# apollo-kotlin
m
I’m looking into some sort of a graceful way of treating 401s on the client side. From the server docs I can see that there’s an error code for `UNAUTHENTICATED`. From the docs I can also see that this’d mean that the HTTP response status code would be still 200 and thus the error goes into the
errors
field. Looking at the handling of the errors field I can see the following: 1.
errors
is nullable 2.
errors.extension
is nullable 3.
extension
might, or might not, contain the 401 code To me this seems quite confusing and I guess means writing something like so to see if server returned 401:
result.errors?.any { err -> err.extensions?.get("code") == "Unauthorized" }
Using the
dataAssertNoErrors
as suggested by client docs doesn’t really seem suitable as it effectively just turns all the possible errors into a string. I feel that I must be missing something here, so would be great to know if I’ve gone off the tracks 😄?
b
What you say looks 100% correct 🙂
dataAssertNoErrors
is a shortcut that can be useful when you don't really care about the type of error. Otherwise use
.errors
as you do in your snippet.
m
Thank you 👍 Is it possible to deserialize the error input into a POJO with an adapter, or is it necessary to go through the error object as described above?
The deserialization would be useful in the following (non-401) scenario. Client sends user input to server via a mutation, however, the input is constrained by max & min lengths:
Copy code
"property": "a_property_name",
              "children": [
                {
                  "property": "a_sub_property_name",
                  "children": [],
                  "constraints": {
                    "isNotEmpty": "a_sub_property_name should not be empty",
                    "minLength": "a_sub_property_name must be longer than or equal to 5 characters",
                    "maxLength": "a_sub_property_name must be shorter than or equal to 100 characters"
                  }
b
Hmm we don't have anything like that for now, you'll have to manually write the adapter. It's an interesting idea though!
m
Thanks 👍 The above
constraints
property comes from https://github.com/typestack/class-validator actually, but nonetheless, it’s more or less the same data structure for the default Apollo errors. To give an example: I have a Mutation with 10 fields, each. with their own constraints. I am wondering what are the options to handle the errors properly? As per your above message, I guess at least one way to do it is to parse the error manually from the
extensions
. I guess another option is to write custom errors on the backend side?
Effectively either one of these will result in the same work on the client-side, which is custom adapter to map the response to a POJO
I’m new to GraphQL and as such I’m not really sure on which way to go here, or if there’s a “cleaner” way of doing the error handling on both client+server 🤔 I find it a bit odd to parse through
extensions: Map<String, Any?>?
To add to my list of messages, one option here might be for backend to provide localised error messages as part of the error payload 🤷
b
Yes that's correct - whatever the contents of
errors
, since it's not part of the schema, no parsers can be automatically generated to ease decoding on the client side. Another way to see it is that the schema could be changed to return, for instance, an Union type of either your result, or an Error type which is defined in the schema. That way you would get a generated parser. But 1/ I'm not really sure this is to be recommended - that could complexify your queries (now you need to deal with polymorphism / fragments) 2/ you'd still need to check the
errors
at the call site (so now you have 3 cases: network error / GraphQL error / your domain error via this union 3/ In your specific case it looks like the error format is of a 'tree' structure. That won't help writing the queries 😅