kataras/iris · error
unsupported response body type: %T
Error message
unsupported response body type: %T
What it means
Client.ReadPlain reads a response body as plain text and only knows how to bind it into *[]byte, *string, or *int. If dest is any other type it returns this error naming the concrete Go type it received. It is a programming/usage error: the wrong destination pointer was passed to ReadPlain.
Source
Thrown at x/client/client.go:456
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
switch ptr := dest.(type) {
case *[]byte:
*ptr = body
return nil
case *string:
*ptr = string(body)
return nil
case *int:
*ptr, err = strconv.Atoi(string(body))
return err
default:
return fmt.Errorf("unsupported response body type: %T", ptr)
}
}
// GetPlainUnquote reads the response body as raw text and tries to unquote it,
// useful when the remote server sends a single key as a value but due to backend mistake
// it sends it as JSON (quoted) instead of plain text.
func (c *Client) GetPlainUnquote(ctx context.Context, method, urlpath string, payload any, opts ...RequestOption) (string, error) {
var bodyStr string
if err := c.ReadPlain(ctx, &bodyStr, method, urlpath, payload, opts...); err != nil {
return "", err
}
s, err := strconv.Unquote(bodyStr)
if err == nil {
bodyStr = s
}
return bodyStr, nilView on GitHub (pinned to 7bedaf55a0)
Solutions
- Pass a pointer to string, []byte, or int as dest (e.g. var s string; client.ReadPlain(ctx, &s, ...)).
- If you need structured data, use ReadJSON instead of ReadPlain.
- For custom types, read into a *string/*[]byte and convert/unmarshal manually afterwards.
- Read the %T in the error message to identify the wrongly-typed variable at the call site.
Example fix
// before var result map[string]any err := client.ReadPlain(ctx, &result, http.MethodGet, "/api/value", nil) // after var s string err := client.ReadPlain(ctx, &s, http.MethodGet, "/api/value", nil) // or use ReadJSON for structured types
Defensive patterns
Strategy: type-guard
Validate before calling
func readPlainDestOK(dest any) bool {
switch dest.(type) {
case *string, *[]byte, *int:
return true
default:
return false
}
}
// if !readPlainDestOK(&dest) { use ReadJSON or convert dest } Type guard
func isReadPlainDest(dest any) bool {
switch dest.(type) {
case *string, *[]byte, *int:
return true
}
return false
} Try / catch
if err := client.ReadPlain(ctx, dest, method, path, nil); err != nil {
if strings.HasPrefix(err.Error(), "unsupported response body type:") {
// programmer error: wrong dest type; do not retry, fix call site
return fmt.Errorf("ReadPlain misuse: %w", err)
}
return err
} Prevention
- Only pass &string, &[]byte or &int to ReadPlain; route structured types to ReadJSON.
- Watch out for named/alias types (*MyString is not *string in a type switch).
- Wrap ReadPlain in a small helper with a constrained generic signature: func readPlain[T ~string | ~[]byte | ~int].
- Add a unit test per call site exercising the dest type.
When it happens
Trigger: Calling client.ReadPlain(ctx, dest, method, urlpath, ...) where dest is not *[]byte, *string or *int — e.g. passing a *map[string]any, *struct pointer, or *float64. Also triggered indirectly if GetPlainUnquote's internal *string path is altered; GetPlainUnquote itself is safe since it always passes a *string.
Common situations: Refactoring code from ReadJSON to ReadPlain and forgetting to change the destination to a plain-type pointer; copy-pasting a ReadJSON call with a struct pointer into ReadPlain; passing a typed alias like *MyString (whose underlying type differs at the type-switch level) instead of *string.
Related errors
- plain text response should accept a *string or a *[]byte
- client.Do: default request option[%d]: %w
- DayTime: unknown type of: %T
- ISO8601: unknown type of: %T
- KitchenTime: unknown type of: %T
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/12a0400a702b232f.
Report an issue: GitHub.