Replies: 9 comments 20 replies
-
Error Handling Option 1Status QuoThere is no way to catch errors. Errors produced by Required Designators ( ExampleSchematype Business {
name: String
isStarred: Boolean
} Query{
business {
name
isStarred!
}
} Response{
"errors": [
{
"message": "Cannot return null for non-nullable field Business.isStarred.",
// ...
}
],
"data": {
"business": {
"name": "Nobu",
"isStarred": null
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Error Handling Option 2Errors caused by CCN are treated as distinct from all existing errorsWhen a client uses CCN, they are indicating that they are capable of handling the error case, so a CCN error may be treated as less serious than other existing errors, or treated as handled-by-default. We have a few options here. What happens to handled errorsA) Exclude CCN errors from the Each of these has various pros and cons, which we can discuss further if this option is selected for development ExampleSchematype Business {
name: String
isStarred: Boolean
} Query{
business {
name
isStarred!
}
} Option A Response{
"data": {
"business": {
"name": "Nobu",
"isStarred": null
}
}
} Option B Response{
"errors": [
{
"message": "Cannot return null for non-nullable field Business.isStarred.",
"namespace": "client_controlled_nullabilty"
// ...
}
],
"data": {
"business": {
"name": "Nobu",
"isStarred": null
}
}
} Option C Response{
"errors": [
{
"message": "Cannot return null for non-nullable field Business.isStarred.",
"isHandled": true
// ...
}
],
"data": {
"business": {
"name": "Nobu",
"isStarred": null
}
}
} Option D Response{
"handledErrors": [
{
"message": "Cannot return null for non-nullable field Business.isStarred."
// ...
}
],
"data": {
"business": {
"name": "Nobu",
"isStarred": null
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Error Handling Option 3Query syntax is introduced to catch errorsErrors are caught by the nearest catching syntax. In the event that errors are not caught, they are treated as they would be in status quo ie they end up in the errors array. What happens to handled errorsA) Exclude caught errors from the There are two additional options associated with this approach. E) The syntax catches CCN errors ExampleFor the purposes of this example, error catching syntax will be Schematype Business {
name: String
isStarred: Boolean
} Query 1{
business {
name
isStarred!
}
} Response 1{
"errors": [
{
"message": "Cannot return null for non-nullable field Business.isStarred.",
// ...
}
],
"data": {
"business": {
"name": "Nobu",
"isStarred": null
}
}
} Query 2{
business {
name
isStarred! @catch
}
} Response 2{
"handledErrors": [
{
"message": "Cannot return null for non-nullable field Business.isStarred."
// ...
}
],
"data": {
"business": {
"name": "Nobu",
"isStarred": null
}
}
} Query 3{
business @catch {
name
isStarred!
}
} Response 3{
"handledErrors": [
{
"message": "Cannot return null for non-nullable field Business.isStarred."
// ...
}
],
"data": {
"business": {
"name": "Nobu",
"isStarred": null
}
}
} Query 4{
business {
name @catch
isStarred!
}
} Response 4{
"errors": [
{
"message": "Cannot return null for non-nullable field Business.isStarred.",
// ...
}
],
"data": {
"business": {
"name": "Nobu",
"isStarred": null
}
}
} |
Beta Was this translation helpful? Give feedback.
-
I suggest to change some terminology and naming. CCN -> "Null Assertion" The error message you use in samples is "isStarred for business could not be fetched.". It sounds like server failed at something and reports it as a server-side error. I think this is a misrepresentation - these are not server errors or failures in any way. Lets look at the following example. There are Employees, of two kinds - FullTime and Hourly; there are 2 nullable fields: Salary for FullTime and HourRate for Hourly employees. Again, salary field is Nullable. We are at the page for FullTime employee details, so client sends a query: query {
employee(id: 123) {
name
salary!
}
} The client is requesting: "give me employee 123. I know she is FullTime, so salary should not be null. But just to be sure, please check it and let me know if it is null." And the server responds: "here it is, your 123. Data retrieved OK, no errors. As for your your assumption about salary - it is wrong, salary field is null. You probably got wrong Id, or whatever." The point is - there was NO Error on server side, it retrieved the data and returned it to the client. As for how to return the message, I do not see a problem returning the message in errors list, just add some code/tag/marker identifying it as FailedAssertion. The name of the feature - client controlled nullability (CCN) - is misleading too. Client controls nothing. Client asks the server to perform an extra assertion over a value before returning the response. How about 'Null Assertions' instead of CCN? - so '!' is a non-null assertion executed by the server. Note 1: It is possible hypothetically that employee 123 is FullTime type but salary is null, which means data integrity error on the server - but this would/should manifest inside server code, differently and much earlier during data retrieval, and server would throw real error (server error) and return it with response - regardless if there's ! or not. But this has nothing to do with CCN. Note 2: when talking about errors, use of terms/keywords: catch/caught errors, handledErrors, isHandled. These terms are quite confusing. Technically, all errors are caught and handled on the server. Otherwise, if server process does not handle an error, it bubbles up (as exception?), and if it is not caught it crashes the server process; and then your server is down, completely, dead. That's a conventional understanding of unhandled error in an app - the OS kills it. So all errors we're talking about here are Caught/Handled - since we have some intelligent response from the server. Thus 'isHandled' etc - sounds strange; all errors are handled some way or another EDIT on Feb 12: after this comment was posted, the error messages in the original code samples in the preceding entries were edited and changed to 'Cannot return null for...'. |
Beta Was this translation helpful? Give feedback.
-
For now it is just a few people, but I am talking about future spec readers, thousands and thousands of them. Again, conceptually CCN does NOT make sense at all, for a newbie or an old timer; client does NOT change anything on the server (like nullability of the field), so client controls nothing. It only humbly asks the server to run an assertion, a simple check on result. Even if this check fails, it does not signal any error on the server; it is just failed client's assumption. |
Beta Was this translation helpful? Give feedback.
-
I'm not sure I have enough understanding of GraphQL intricacies yet to know whether this is possible or not for scalar fields, but I think it would make most sense to treat object fields decorated with Modifying the example from option 3 this would look like: Query 3 {
business @catch {
... on Business {
name
isStarred!
}
... on Error {
message
}
}
} Response 3 {
"data": {
"business": {
"__typename": "Error",
"message": "Cannot return null for non-nullable field Business.isStarred."
}
}
} (Edit: updated to be explicit about using match syntax.) |
Beta Was this translation helpful? Give feedback.
-
(reposted from other thread) Two things, about '?' as error boundary
|
Beta Was this translation helpful? Give feedback.
-
One more option I've been thinking about that I want to throw out there to see if it has legs: Provide server developers with more robust per-field error handling capabilitiesWe allow server developers to provide an error handling function for each field alongside a resolver. This way if an error is propagated from one field through multiple parents, each parent will be able to actually choose how it wishes to handle that error rather than leaving it for the nullability of each field to decide.
This will allow servers to choose how they'd like to react not just to CCN errors, but all errors. It will enable developers to do things like return a default value for a field in the event of an error, or decide that certain errors should not be returned to clients. This would be a pretty substantial change, and is likely overkill for what we're trying to do here. It could be a proposal all on its own. Does it solve the problems folks are trying to solve here? |
Beta Was this translation helpful? Give feedback.
-
Hello! It's been a while. The Client Controlled Nullability RFC is now winding down in favor of True Schema Nullability, so I'll be closing CCN related issues, PRs, and discussions. All further discussion should be rerouted to one of the following: Additionally, we're in the process of removing the CCN experimental flag from graphql-js. TL;DR of the new proposal(s) is that instead of allowing clients to adapt to imprecise schema definitions, our new approach is to find ways to allow schema authors to provide the precision that's been missing. There are a few different approaches to that which you can read about in the discussions above. Apollo and a couple other schema authors are in the process of putting together experiments, so if you'd like to have input or beta test the new proposal(s), reach out to us either in the Nullability Working Group, or in the #nullability-wg channel on Discord. |
Beta Was this translation helpful? Give feedback.
-
Spec changes
To get a better idea of where we stand, I'll add a poll so people can vote on their favorite option. This vote is non-binding, and is only one factor in choosing which syntax we land on I'll open new threads for people to discuss each option below.
I'm going to try and separate null propagation and error handling discussion. In the original thread and during working group discussions, the conflation of the two has been causing some confusion about what options exist I think. For example, we could feasibly decide on any combination of (status quo null propagation/propagation to the nearest question mark) and (caught errors marked handled/caught errors put in a separate array/caught errors include destroyed data).
For some context on this discussion, some clients react to errors by throwing out the entire response. Since CCN is likely to create quite a few more errors than usual, and they are errors that the client is indicating it can handle, some commenters have felt that a means to handle errors needs to be introduced alongside CCN for it to be tenable for more sophisticated use cases.
Status Quo (No Error Handling)
Errors Caused By CCN Are Treated As Distinct From All Existing Errors
Query Syntax Is Introduced To Catch Errors
Update (March 6th, 2022): Folks at the working group meeting didn't feel like we'd explored the full breadth of the options for error handling, and wanted more time to further discuss.
Beta Was this translation helpful? Give feedback.
All reactions