Skip to content

client: implement interface{ Is(error) bool } on generated errors #1413

Open
@kushuh

Description

@kushuh

Problem

The template for generating errors only implements the Error() string interface.

Since the generated error is a struct, errors.Is() cannot be used directly. The only way to check errors is to use the more cumbersome errors.As() alternative.

_, err := client.Method(ctx)

var ogenError *generated.UnexpectedErrorStatusCode

if errors.As(err, &ogenError) {
  if ogenError.StatusCode == http.StatusUnauthorized {
    // ...
  }
}

Proposal

Golang allows errors to implement the interface{ Is(error) bool }, which allows complex errors to be scanned with errors.Is. Something as straightforward as:

// Code generated by ogen.

func (s *UnexpectedErrorStatusCode) Error() string {
  return fmt.Sprintf("code %d: %+v", s.StatusCode, s.Response)
}

func (s *UnexpectedErrorStatusCode) Is(err error) bool {
  var cmp *UnexpectedErrorStatusCode

  if !errors.As(err, &cmp) {
    return false
  }

  if cmp.StatusCode != s.StatusCode {
    return false
  }

  return true
}

Could allow one-line checks like this:

if errors.Is(err, &generated.UnexpectedErrorStatusCode{StatusCode: http.StatusUnauthorized}) {}

Or even allow for nice switch statements:

unauthorizedError := &generated.UnexpectedErrorStatusCode{StatusCode: http.StatusUnauthorized}
forbiddenError := &generated.UnexpectedErrorStatusCode{StatusCode: http.StatusForbidden}

switch {
case errors.Is(err, unauthorizedError):
  // Unauthorized.
case errors.Is(err, forbiddenError):
  // Forbidden.
default:
  // Unhandled.
}

References

This feature would be insanely helpful for integration tests. Also it could improve code quality on applications that use the ogen client.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions