Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: AIP-193 – Errors #3

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

feat: AIP-193 – Errors #3

wants to merge 3 commits into from

Conversation

lukesneeringer
Copy link
Contributor

@lukesneeringer lukesneeringer commented Sep 3, 2020

This adds a generic AIP for errors. There is probably a decent bit for us to discuss here.

Some high-level notes:

  • I decided to represent expected JSON interfaces using TypeScript (rather than JSONSchema), which I perceive to be much better for human readability.
  • We should discuss/debate the proposed Error interface. It is mostly similar to what Google uses but with two fields "promoted" (we have a huge mea culpa here).
  • I did not discuss any common headers related to error handling (e.g. Retry-After). I personally think that Retry-After gets covered in AIP-194, and I could not think of any others that warranted inclusion here.
  • I chose for now not to use {% sample %} as I could not think of how a full file would add any context that the AIP should elide (which I think is my standard for using {% sample %}, although this is 100% intuition and we should discuss it).

I expect this is an area where everyone will need to make changes, but I also notice that entire sections can probably be adopted by everyone (e.g. "Messages"), so I think this should work reasonably well.

Looking forward to the discussion on this.

This adds a generic AIP for errors. There is probably a decent bit
for us to discuss here.

Some high-level notes:

- I decided to represent expected JSON interfaces using TypeScript
  (rather than JSONSchema), which I perceive to be much better
  for human readability.
- We should discuss/debate the proposed Error interface. It is
  mostly similar to what Google uses but with two fields "promoted"
  (we have a huge _mea culpa_ here).
- I did not discuss any common _headers_ related to error handling
  (e.g. `Retry-After`). I personally think that `Retry-After` gets
  covered in AIP-194, and I could not think of any others that
  warranted inclusion here.

I expect this is an area where everyone will need to make changes,
but I also notice that entire sections can probably be adopted
by everyone (e.g. "Messages"), so I think this should work
reasonably well.

Looking forward to the discussion on this.
@lukesneeringer lukesneeringer requested a review from a team as a code owner September 3, 2020 02:19
@lukesneeringer
Copy link
Contributor Author

lukesneeringer commented Sep 3, 2020

Note:

@lukesneeringer lukesneeringer changed the title feat: AIP-193 feat: AIP-193 – Errors Sep 3, 2020
by using appropriate HTTP codes:

- Successful responses **must** use HTTP status codes between 200 and 399.
- Errors indicating a problem with the user's request **must** use HTTP status
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about this briefly in the WG, and I'm posting the question here again.

For parts of the proposal that do not map well with one or more of the "implementations" (say GraphQL in this case). How do we want to represent divergence?

For this specific case, in GraphQL there is a distinction between how to represent before GraphQL execution errors (e.g: malformed HTTP request to the server should yield 400) and say validation/business logic errors (e.g: GraphQL query syntax is invalid would yield a 200 status code with errors populated in the errors block of the body of the HTTP response)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect a GraphQL AIP to override this section.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @innou is what you're saying how GraphQL actually does it? returning success codes for cases where there are syntax errors in the request? that sounds like a bad idea to me, but if that's how it's done, there's little that can be done. in my mind, that would not be a good pattern to recommend. RFC 6231 is pretty clear on that one, i think:

400 Bad Request:
  The 400 (Bad Request) status code indicates that the server cannot or
  will not process the request due to something that is perceived to be
  a client error (e.g., malformed request syntax, invalid request
  message framing, or deceptive request routing).

@rhamiltonsf
Copy link

I chose for now not to use {% sample %} as I could not think of how a full file would add any context that the AIP should elide (which I think is my standard for using {% sample %}, although this is 100% intuition and we should discuss it).

Raised this in the other PR. I would like your thoughts on what the sample should be and we should try to formalize it so that anybody (if anybody else writes these) could provide a sample and it is consistent with the others.


### Structure

Error responses **should** conform to the following interface:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing this is where you were expecting most of the comments :)

My recommendation would be to use RFC 7807

The short of it would be this:

interface Error {
  //URL formated identifier. Does not have to be a functioning URL
  type: string;

  //A human readable description of the problem. Should not change from occurrence to occurrence.
  title?: string

  //The HTTP status code
  status?: number

  //A human readable description of the problem that is unique to this occurrence.
  detail?: string

  //A URI reference unique to the occurrence of the problem. May or may not reveal additional information about the problem.
  instance?: string
}

Additional properties may be added to the root level of the object to convey information unique to the error.

Note that status is optional. That's because it is expected to already be a part of the response. Adding it here is redundant (and IMHO should be discouraged).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although we based our AIP 193 on RFC 7807, you might be interested in seeing how ours differs from the RFC as an extension use case: https://github.com/rhamiltonsf/sf.aip/blob/master/aip/0193.md

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one of the reasons why status is in there is to allow RFC 7807 to be used for representing problem reports in a self-contained way. and btw, type is optional, too: everything is optional.

Base automatically changed from master to main February 10, 2021 22:07

### Messages

Error messages **should** help a reasonably technical user understand and

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hudlow Who is the intended audience of these errors?

  • @rhamiltonsf discussed whether we should use RFC 7807, which may satisfy both requirements.

}
```

### Partial errors

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhudlow and @saurabhsahni, should we allow for the return of multiple errors?

  • @hudlow, @rhamiltonsf Probably not disparate issues (i.e. Authentication AND invalid body), however, this might need to be explored more for bulk and batch operations.
  • @saurabhsahni, @hudlow errors that are of the same type can be returned together.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rhamiltonsf: We got blocked on the batch/bulk API recommendations last time when we chatted about this

  • @hudlow and @rhamiltonsf: In interest of moving this AIP forward, we may want to redact recommendation around batch/bulk APIs for now.

@google-cla google-cla bot added the cla: yes label Nov 4, 2021
}
```

### Partial errors

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rhamiltonsf: We got blocked on the batch/bulk API recommendations last time when we chatted about this

  • @hudlow and @rhamiltonsf: In interest of moving this AIP forward, we may want to redact recommendation around batch/bulk APIs for now.

**should** be provided in a `details` field. If even more information is
necessary, the service **should** provide a link where a reader can get more
information or ask questions to help resolve the issue.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about adding some examples like 👇 here?


Below are some examples of good errors and not so good errors:

    ❌  Invalid Book Name.
    ✅  Book name must be between 5 and 50 characters.

    ❌  Access is denied
    ✅  Only admin users have access to this resource.

    ❌  Bad input
    ✅  'ID' must be provided in the input


### Structure

Error responses **should** conform to the following interface:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

details: ?any[];
}
```

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about describing code here?


  • The code field is the HTTP status code value returned as number. It MUST match the status code in the HTTP response.

```typescript
interface Error {
// The HTTP status code.
code: number;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would very much appreciate it if this were renamed, both to align with RFC 7807 and also to not conflict with OCI Errors (which use code to communicate the specific error type).

Suggested change
code: number;
status: number;

// The source of the error (usually the registered service address of the
// tool or product that generates the error).
// Example: "pubsub.googleapis.com"
domain: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name also seems very strange to me, as opposed to e.g. source or scope or namespace or some suffixed variant thereof.

// The source of the error (usually the registered service address of the
// tool or product that generates the error).
// Example: "pubsub.googleapis.com"
domain: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And shouldn't it be optional?

type: string;

// An array of additional error details.
details: ?any[];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about recommending a structure for details. Example:

details: [
 { 
   message: string;
   type: string;
   ...
 }
]

@shwoodard
Copy link

I think we want to orient this AIP towards how error handling should leverage ErrorInfo. I will fork and suggest edits.

@dret
Copy link

dret commented Dec 3, 2021 via email

@rhamiltonsf
Copy link

rhamiltonsf commented Dec 6, 2021 via email

@dret
Copy link

dret commented Dec 7, 2021 via email

@shwoodard shwoodard self-requested a review December 7, 2021 17:52
@shwoodard shwoodard mentioned this pull request Dec 14, 2021
@rhamiltonsf
Copy link

rhamiltonsf commented Dec 17, 2021 via email

@dret
Copy link

dret commented Dec 18, 2021 via email

@rhamiltonsf
Copy link

sounds good. would you have an AIP in mind or can i take any? what's the group's process ho to create and discuss such a proposal? thanks and cheers, dret.

-- erik wilde | @.*** | | http://dret.net/netdret | | http://twitter.com/dret |

Anything in the TODO column in this project is fair game.

The process is pretty open. Make the desired changes, and then submit for review. We review changes in our weekly meeting, or if you have questions/concerns, you can raise those in that meeting as well.

Copy link

@mkistler mkistler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. 👍

I think the current content is good enough as the initial version of this AIP. It communicates the most essential guidance, which is that you should have a standard error format. The details are likely to vary by company, so we shouldn't dwell to hard on that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants