sdk-codegen icon indicating copy to clipboard operation
sdk-codegen copied to clipboard

Golang SDK v3 does not return error context from API

Open Jberlinsky opened this issue 4 years ago • 1 comments

When issuing a request to the Golang API that triggers an HTTP 4XX error (e.g. a 422 validation error), the Swagger API will return useful error context, e.g.:

{
  "message": "Validation Failed",
  "errors": [
    {
      "field": "dialect",
      "code": "missing_field",
      "message": "This field is required.",
      "documentation_url": "http://docs.looker.com/"
    },
    {
      "field": "database",
      "code": "missing_field",
      "message": "This field is required.",
      "documentation_url": "http://docs.looker.com/"
    },
    {
      "field": "db_timezone",
      "code": "invalid",
      "message": "Must specify a database timezone when user timezones are activated.",
      "documentation_url": "http://docs.looker.com/"
    },
    {
      "field": "max_connections",
      "code": "invalid",
      "message": "Max connections must be an integer between 5 and 100.",
      "documentation_url": "http://docs.looker.com/"
    }
  ],
  "documentation_url": "http://docs.looker.com/"
}

However, the Golang SDK doesn't seem to decode these error messages when a failure is encountered (see https://github.com/looker-open-source/sdk-codegen/blob/main/go/rtl/auth.go#L138). This leaves a user of the SDK in the unfortunate position of having to:

  1. Dump the request object to JSON
  2. Go to the Looker Swagger UI and enter the transposed JSON request
  3. Inspect errors there
  4. Make changes in the Golang SDK caller
  5. Repeat as needed

This also makes it difficult to write effective integration tests for erroneous states.

Jberlinsky avatar Aug 11 '21 13:08 Jberlinsky

Hey! This is a great call out.

We already have generated Error and ValidationError struct types.

We can make use of these types and json decode the error responses. To follow error conventions and not break downstream dependencies, we'd need to define a new Error struct that implements the error interface .

Something like this:

type ResponseError struct {
  StatusCode int
  Error v4.Error
  ValidationError v4.ValidationError
}

func (r *ResponseError) Error() string {
	return fmt.Sprintf("...")
}

Though this would couple a custom Go SDK typing to our swagger spec. So not ideal, but also it's unlikely the swagger spec errors will change.

jeremytchang avatar Mar 16 '22 23:03 jeremytchang