diff --git a/huma.go b/huma.go index f6b14561..9a21d864 100644 --- a/huma.go +++ b/huma.go @@ -1421,7 +1421,11 @@ var reRemoveIDs = regexp.MustCompile(`\{([^}]+)\}`) // This function can be overridden to provide custom operation IDs. var GenerateOperationID = func(method, path string, response any) string { action := method - body, hasBody := deref(reflect.TypeOf(response)).FieldByName("Body") + t := deref(reflect.TypeOf(response)) + if t.Kind() != reflect.Struct { + panic("Response type must be a struct") + } + body, hasBody := t.FieldByName("Body") if hasBody && method == http.MethodGet && deref(body.Type).Kind() == reflect.Slice { // Special case: GET with a slice response body is a list operation. action = "list" @@ -1443,7 +1447,11 @@ var GenerateOperationID = func(method, path string, response any) string { // This function can be overridden to provide custom operation summaries. var GenerateSummary = func(method, path string, response any) string { action := method - body, hasBody := deref(reflect.TypeOf(response)).FieldByName("Body") + t := deref(reflect.TypeOf(response)) + if t.Kind() != reflect.Struct { + panic("Response type must be a struct") + } + body, hasBody := t.FieldByName("Body") if hasBody && method == http.MethodGet && deref(body.Type).Kind() == reflect.Slice { // Special case: GET with a slice response body is a list operation. action = "list" diff --git a/huma_test.go b/huma_test.go index 77f1887a..5607e82b 100644 --- a/huma_test.go +++ b/huma_test.go @@ -1904,3 +1904,15 @@ func BenchmarkHandlerFunc(b *testing.B) { } }) } + +func TestGenerateFuncsPanicWithDescriptiveMessage(t *testing.T) { + var resp *int + assert.PanicsWithValue(t, "Response type must be a struct", func() { + huma.GenerateOperationID("GET", "/foo", resp) + }) + + assert.PanicsWithValue(t, "Response type must be a struct", func() { + huma.GenerateSummary("GET", "/foo", resp) + }) + +}