gofiber/fiber · error

failed to read response

Error message

failed to read response: %w

What it means

After the handler runs, the TestClient parses the handler's response via httpReadResponse(buffer, req). If the response doesn't parse as valid HTTP (bad status line, malformed headers, chunked-encoding errors), the wrapped error is returned. Empty responses are mapped to ErrTestGotEmptyResponse separately.

Solutions

  1. Use Fiber's standard response APIs (c.Status, c.Set, c.Write) so responses always serialize cleanly.
  2. Avoid hijacking or writing raw bytes to the underlying fasthttp connection under test.
  3. Inspect the wrapped error to localize the parse failure.

Example fix

// before
app.Get("/", func(c fiber.Ctx) error {
    c.Response().Header.Set("X-Bad", "a\nb")
    return c.SendString("ok")
})

// after
app.Get("/", func(c fiber.Ctx) error {
    c.Set("X-Good", "a-b")
    return c.SendString("ok")
})
Defensive patterns

Strategy: validation

Validate before calling

// Use fiber's response APIs so output is always well-formed HTTP
app.Get("/", func(c fiber.Ctx) error {
    c.Set("X-Good", "a-b")
    return c.SendString("ok")
})

Try / catch

resp, err := app.Test(req)
if err != nil {
    return fmt.Errorf("response parse failed in test client: %w", err)
}

Prevention

When it happens

Trigger: A handler under test writes a response that isn't well-formed HTTP: invalid status code text, illegal header bytes, broken chunked encoding, or hijacked connections.

Common situations: Custom serializers writing raw bytes; middleware that hijacks the connection; manually setting headers with control characters; version mismatches between handler and parser expectations.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/5b68a930b6aaccbd. Report an issue: GitHub.

Appendix: source

Thrown at app.go:1492

	}

	// Check for errors
	if err != nil && !errors.Is(err, fasthttp.ErrGetOnly) && !errors.Is(err, errTestConnClosed) {
		return nil, err
	}

	// Read response(s)
	buffer := bufio.NewReader(&conn.w)

	var res *http.Response
	for {
		// Convert raw http response to *http.Response
		res, err = httpReadResponse(buffer, req)
		if err != nil {
			if errors.Is(err, io.ErrUnexpectedEOF) {
				return nil, ErrTestGotEmptyResponse
			}
			return nil, fmt.Errorf("failed to read response: %w", err)
		}

		// Break if this response is non-1xx or there are no more responses
		if res.StatusCode >= http.StatusOK || buffer.Buffered() == 0 {
			break
		}

		// Discard interim response body before reading the next one
		if res.Body != nil {
			if _, errCopy := io.Copy(io.Discard, res.Body); errCopy != nil {
				return nil, fmt.Errorf("failed to discard interim response body: %w", errCopy)
			}
			if errClose := res.Body.Close(); errClose != nil {
				return nil, fmt.Errorf("failed to close interim response body: %w", errClose)
			}
		}
	}

View on GitHub (pinned to a105acad6c)