diff --git a/generated/stackstate_api/client.go b/generated/stackstate_api/client.go index 2c4b740d..62a231c2 100644 --- a/generated/stackstate_api/client.go +++ b/generated/stackstate_api/client.go @@ -524,7 +524,7 @@ func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err err } return nil } - return errors.New("undefined response type") + return errors.New(fmt.Sprintf("fatal: could not unmarshal content type: '%s' into '%T'", contentType, v)) } // Add a file to the multipart request diff --git a/internal/common/common_cli_errors.go b/internal/common/common_cli_errors.go index b040db92..9de77e23 100644 --- a/internal/common/common_cli_errors.go +++ b/internal/common/common_cli_errors.go @@ -51,28 +51,33 @@ func NewConnectError(err error, apiURL string, serverResponse *http.Response) CL messages = append(messages, apiErr.Message) } errMessage = strings.Join(messages, ", ") - // Some responses do not yield more than the 401, others give in the body the error message as the RefreshToken failed or so - if errMessage == "" { - errMessage = "invalid api-token" - } - } else { - errMessage = err.Error() + } + + if errMessage == "" { + errMessage = string(apiErr.Body()) } } else { errMessage = err.Error() } return StdCLIError{ - Err: fmt.Errorf("could not connect to %s: %s\n"+ + Err: fmt.Errorf("authentication failed when connecting to %s: %s\n"+ "For more information: https://l.stackstate.com/cli-invalid-api-token", apiURL, errMessage), exitCode: ConnectErrorExitCode, } - } else { + } + + if apiErr, ok := err.(*stackstate_api.GenericOpenAPIError); ok { return StdCLIError{ - Err: fmt.Errorf("could not connect to %s (%s)", apiURL, err), + Err: fmt.Errorf("could not connect to %s (%s): %s", apiURL, err.Error(), string(apiErr.Body())), exitCode: ConnectErrorExitCode, } } + + return StdCLIError{ + Err: fmt.Errorf("could not connect to %s due to %s: ", apiURL, err), + exitCode: ConnectErrorExitCode, + } } func NewCLIArgParseError(err error) CLIError { diff --git a/internal/printer/printer.go b/internal/printer/printer.go index b677a68e..23fecdb8 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -193,6 +193,11 @@ func (p *StdPrinter) printCLIError(err common.CLIError) { } } } + } else if isErrorResponse && strings.Split(resp.Header.Get("Content-Type"), ";")[0] == "text/plain" { + bodyb, err := io.ReadAll(resp.Body) + if err == nil { + bodyStr = string(bodyb) + } } color.Fprintf(p.stdErr, diff --git a/internal/printer/printer_test.go b/internal/printer/printer_test.go index aaabd09a..57a66f8e 100644 --- a/internal/printer/printer_test.go +++ b/internal/printer/printer_test.go @@ -154,6 +154,21 @@ func TestPrintCLIErrorWith503WithColor(t *testing.T) { assert.Equal(t, expected, stdErr.String()) } +func TestPrintCLIErrorWithTextResponse(t *testing.T) { + p, _, stdErr := setupPrinter() + p.SetUseColor(true) + + resp := http.Response{ + Status: "403 Forbidden", + Header: map[string][]string{"Content-Type": {"text/plain; charset=UTF-8"}}, + Body: io.NopCloser(strings.NewReader(`bigproblem`)), + } + p.PrintErr(common.NewResponseError(fmt.Errorf(""), &resp)) + + expected := "\u274C 403 Forbidden\nbigproblem\n" + assert.Equal(t, expected, stdErr.String()) +} + func TestPrintCLIError101WithoutColor(t *testing.T) { p, _, _ := setupPrinter() p.SetUseColor(false)