kataras/iris · error

plain text response should accept a *string or a *[]byte

Error message

plain text response should accept a *string or a *[]byte

What it means

BindResponse dispatches on the response's Content-Type header; when it is plain text it only binds the body into *string or *[]byte. If dest is any other type while the server answered with text/plain, it returns this error. The library is deliberately strict so mismatches between the declared response content type and the destination are caught early.

Source

Thrown at x/client/client.go:528

// the response headers and the dest is a *string.
func BindResponse(resp *http.Response, dest any) (err error) {
	contentType := trimHeader(resp.Header.Get(contentTypeKey))
	switch contentType {
	case contentTypeJSON: // the most common scenario on successful responses.
		return json.NewDecoder(resp.Body).Decode(&dest)
	case contentTypePlainText:
		b, err := io.ReadAll(resp.Body)
		if err != nil {
			return err
		}

		switch v := dest.(type) {
		case *string:
			*v = string(b)
		case *[]byte:
			*v = b
		default:
			return fmt.Errorf("plain text response should accept a *string or a *[]byte")
		}

	default:
		acceptContentType := trimHeader(resp.Request.Header.Get(acceptKey))
		msg := ""
		if acceptContentType == contentType {
			// Here we make a special case, if the content type
			// was explicitly set by the request but we cannot handle it.
			msg = fmt.Sprintf("current implementation can not handle the received (and accepted) mime type: %s", contentType)
		} else {
			msg = fmt.Sprintf("unexpected mime type received: %s", contentType)
		}
		err = errors.New(msg)
	}

	return
}

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Pass a *string or *[]byte as dest when the response is plain text, then parse (e.g. strconv.Atoi) as needed.
  2. Check resp.Content-Type before binding and choose the right dest type per content type.
  3. If the body should be JSON, fix the server or set/verify the Accept header so the server replies with application/json.
  4. Use Client.ReadPlain instead if you need *int binding of a plain-text body.

Example fix

// before
var n int
err := client.BindResponse(resp, &n) // text/plain body

// after
var s string
if err := client.BindResponse(resp, &s); err != nil { return err }
n, err := strconv.Atoi(strings.TrimSpace(s))
Defensive patterns

Strategy: type-guard

Validate before calling

func bindDestOK(resp *http.Response, dest any) bool {
    ct := resp.Header.Get("Content-Type")
    if i := strings.IndexAny(ct, " ;"); i >= 0 { ct = ct[:i] }
    if ct == "plain/text" {
        switch dest.(type) {
        case *string, *[]byte:
            return true
        default:
            return false
        }
    }
    return true
}

Type guard

func isPlainTextBindDest(dest any) bool {
    switch dest.(type) {
    case *string, *[]byte:
        return true
    }
    return false
}

Try / catch

if err := client.BindResponse(resp, dest); err != nil {
    if strings.Contains(err.Error(), "plain text response should accept") {
        // rebind into a *string and convert manually
        var s string
        return client.BindResponse(resp, &s)
    }
    return err
}

Prevention

When it happens

Trigger: Calling client.BindResponse(resp, dest) where resp.Header.Get("Content-Type") is "text/plain" (compare uses trimHeader, so parameters like charset are trimmed) but dest is e.g. *int, *map[string]any, or a struct pointer — unlike ReadPlain, BindResponse's plain-text branch does not support *int.

Common situations: Reusing one BindResponse call site for responses that may be JSON or plain text and passing an *int (works only if you used ReadPlain, not BindResponse); a server suddenly responding text/plain to an endpoint the client expected JSON from; passing non-pointer values by mistake.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/420cd5ea76910dff. Report an issue: GitHub.