diff --git a/proxmox/api/client.go b/proxmox/api/client.go index 18bd0261..663dc9c9 100644 --- a/proxmox/api/client.go +++ b/proxmox/api/client.go @@ -334,11 +334,22 @@ func validateResponseCode(res *http.Response) error { errRes := &ErrorResponseBody{} err := json.NewDecoder(res.Body).Decode(errRes) - if err == nil && errRes.Errors != nil { + if err == nil { var errList []string - for k, v := range *errRes.Errors { - errList = append(errList, fmt.Sprintf("%s: %s", k, strings.TrimRight(v, "\n\r"))) + if errRes.Errors != nil { + for k, v := range *errRes.Errors { + errList = append(errList, fmt.Sprintf("%s: %s", k, strings.TrimRight(v, "\n\r"))) + } + } + + if errRes.Message != nil && *errRes.Message != "" { + split := slices.Compact(strings.Split(*errRes.Message, "\n")) + // skip empty lines and the first line, which is a duplicate of the HTTP status message + split = slices.DeleteFunc(split, func(s string) bool { + return len(s) == 0 || strings.HasPrefix(s, msg) + }) + errList = append(errList, split...) } msg = fmt.Sprintf("%s (%s)", msg, strings.Join(errList, " - ")) diff --git a/proxmox/api/client_test.go b/proxmox/api/client_test.go index 36706f50..e77215b5 100644 --- a/proxmox/api/client_test.go +++ b/proxmox/api/client_test.go @@ -9,6 +9,7 @@ package api import ( "context" "errors" + "io" "net/http" "reflect" "strconv" @@ -53,6 +54,7 @@ func TestClientDoRequest(t *testing.T) { tests := []struct { name string status string + body string wantErr error }{ {name: "no error", status: "200 OK", wantErr: nil}, @@ -62,6 +64,15 @@ func TestClientDoRequest(t *testing.T) { Code: 500, Message: "Internal Server Error", }}, + { + name: "500 status with body", + status: "500 create sdn zone object failed: 400 Parameter verification failed.", + body: `{"message":"create sdn zone object failed: 400 Parameter verification failed.\nipam: ipam-simple not existing\n","data":null}`, + wantErr: &HTTPError{ + Code: 500, + Message: "create sdn zone object failed: 400 Parameter verification failed. (ipam: ipam-simple not existing)", + }, + }, } for _, tt := range tests { @@ -77,7 +88,7 @@ func TestClientDoRequest(t *testing.T) { return &http.Response{ Status: tt.status, StatusCode: sc, - Body: nil, + Body: io.NopCloser(strings.NewReader(tt.body)), } }), }, diff --git a/proxmox/api/client_types.go b/proxmox/api/client_types.go index c3ee7f77..ecfbd2a4 100644 --- a/proxmox/api/client_types.go +++ b/proxmox/api/client_types.go @@ -20,8 +20,9 @@ type MultiPartData struct { // ErrorResponseBody contains the body of an error response. type ErrorResponseBody struct { - Data *string `json:"data"` - Errors *map[string]string `json:"errors"` + Data *string `json:"data"` + Message *string `json:"message"` + Errors *map[string]string `json:"errors"` } // FileUploadRequest is a request for uploading a file.