gofiber/fiber · error
test: got empty response
Error message
test: got empty response
What it means
Returned by App.Test when reading the synthesized HTTP response hits io.ErrUnexpectedEOF — the in-process server closed the test connection before writing any bytes (app.go:1489-1491). Test() drives the handler through a pipe; if the handler never writes (e.g. calls Ctx.Drop()) the response stream is empty and EOF is translated to this sentinel so callers can distinguish 'no response' from other read failures.
Source
Thrown at app.go:1372
// Hooks returns the hook struct to register hooks.
func (app *App) Hooks() *Hooks {
return app.hooks
}
// State returns the in-process state struct to store global data between handlers.
// State is process-local and is not shared across prefork workers.
func (app *App) State() *State {
return app.state
}
// SharedState returns storage-backed shared state.
// SharedState is prefork-safe when Config.SharedStorage is configured.
func (app *App) SharedState() *SharedState {
return app.sharedState
}
var ErrTestGotEmptyResponse = errors.New("test: got empty response")
// TestConfig is a struct holding Test settings
type TestConfig struct {
// Timeout defines the maximum duration a
// test can run before timing out.
// Default: time.Second
Timeout time.Duration
// FailOnTimeout specifies whether the test
// should return a timeout error if the HTTP response
// exceeds the Timeout duration.
// Default: true
FailOnTimeout bool
}
// Test is used for internal debugging by passing a *http.Request.
// Config is optional and defaults to a 1s error on timeout,
// 0 timeout will disable it completely.View on GitHub (pinned to a105acad6c)
Solutions
- If the empty response is unintended, fix the handler so it always writes a response (c.Send(), c.Status().SendString(), or returning an error that maps to a status) before returning.
- If Drop() is intentional, treat ErrTestGotEmptyResponse as the expected outcome and assert it with errors.Is(err, fiber.ErrTestGotEmptyResponse) rather than require.NoError.
- Set TestConfig.FailOnTimeout=true (the default) so a hung handler surfaces os.ErrDeadlineExceeded instead of silently producing an empty stream.
- Set a non-zero TestConfig.Timeout to bound how long Test() waits before giving up.
Example fix
// before
app.Get("/", func(c fiber.Ctx) error { return c.Drop() })
_, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
require.NoError(t, err) // fails: ErrTestGotEmptyResponse
// after (handler writes a response)
app.Get("/", func(c fiber.Ctx) error { return c.SendString("ok") })
_, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
require.NoError(t, err) Defensive patterns
Strategy: try-catch
Validate before calling
// Before calling app.Test, ensure the handler always writes a response
// (audit the handler). For Drop()-by-design handlers, expect the sentinel:
func runTest(t *testing.T, app *fiber.App, req *http.Request) {
_, err := app.Test(req)
if errors.Is(err, fiber.ErrTestGotEmptyResponse) {
// handler intentionally drops — treat as expected
return
}
if err != nil { t.Fatal(err) }
} Try / catch
resp, err := app.Test(req)
switch {
case errors.Is(err, fiber.ErrTestGotEmptyResponse):
// handler wrote nothing — assert this is intended
case err != nil:
t.Fatalf("unexpected test error: %v", err)
default:
// use resp
} Prevention
- Design handlers to always return either a response or a mapped error status — never silently drop.
- Treat c.Drop() as an explicit decision and pair it with a test that asserts ErrTestGotEmptyResponse.
- Keep TestConfig.FailOnTimeout at its default true so hung handlers surface DeadlineExceeded.
When it happens
Trigger: Calling app.Test(req) against a handler that invokes c.Drop() (test at app_test.go:2946-2959), a handler that panics before writing, or a handler path that returns without producing output. Also reachable when FailOnTimeout is false and the handler still produces nothing within the 1s grace window.
Common situations: Unit-testing handlers that intentionally drop the connection; testing error branches that bypass c.Send(); a misconfigured handler chain where middleware short-circuits with Drop(); TestConfig.Timeout=0 with FailOnTimeout=false amplifying the chance of an empty stream.
Related errors
- binder: suitable content not found to parse body
- failed to dump request: %w
- failed to write: %w
- failed to read response: %w
- binder: map is not convertible to map[string]string or map[s
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/2684baa2dc04e098.
Report an issue: GitHub.