{"id":"5b68a930b6aaccbd","repo":"gofiber/fiber","slug":"failed-to-read-response-w","errorCode":null,"errorMessage":"failed to read response: %w","messagePattern":"failed to read response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app.go","lineNumber":1491,"sourceCode":"\t}\n\n\t// Check for errors\n\tif err != nil && !errors.Is(err, fasthttp.ErrGetOnly) && !errors.Is(err, errTestConnClosed) {\n\t\treturn nil, err\n\t}\n\n\t// Read response(s)\n\tbuffer := bufio.NewReader(&conn.w)\n\n\tvar res *http.Response\n\tfor {\n\t\t// Convert raw http response to *http.Response\n\t\tres, err = httpReadResponse(buffer, req)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, io.ErrUnexpectedEOF) {\n\t\t\t\treturn nil, ErrTestGotEmptyResponse\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"failed to read response: %w\", err)\n\t\t}\n\n\t\t// Break if this response is non-1xx or there are no more responses\n\t\tif res.StatusCode >= http.StatusOK || buffer.Buffered() == 0 {\n\t\t\tbreak\n\t\t}\n\n\t\t// Discard interim response body before reading the next one\n\t\tif res.Body != nil {\n\t\t\tif _, errCopy := io.Copy(io.Discard, res.Body); errCopy != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to discard interim response body: %w\", errCopy)\n\t\t\t}\n\t\t\tif errClose := res.Body.Close(); errClose != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to close interim response body: %w\", errClose)\n\t\t\t}\n\t\t}\n\t}\n","sourceCodeStart":1473,"sourceCodeEnd":1509,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/app.go#L1473-L1509","documentation":"Returned by App.Test (app.go:1491) when http.ReadResponse (httpReadResponse) fails to parse the response the handler wrote, excluding the io.ErrUnexpectedEOF case (which maps to ErrTestGotEmptyResponse). It means the bytes on the testConn do not form a valid HTTP response — the handler produced malformed output or the connection was reset mid-response.","triggerScenarios":"A handler under test writing an invalid status line, missing/oversized headers, or a chunked body that breaks framing; the handler panicking after partial writes; the response exceeding the testConn buffer; a timeout closing the conn mid-response (FailOnTimeout interactions).","commonSituations":"Handlers that write raw bytes via fasthttp in unusual ways; custom serializers emitting non-RFC-compliant responses; tests that hit the 1s default timeout on slow handlers; gzip/compression framing bugs.","solutions":["Inspect the wrapped error to locate the parse failure (header line, chunk size, body EOF).","Increase TestConfig.Timeout (or set FailOnTimeout:false) if the handler is legitimately slow.","Test the handler in isolation to confirm it emits a well-formed HTTP response.","Verify Content-Length / Transfer-Encoding headers match the body the handler writes."],"exampleFix":"// before\nresp, err := app.Test(req) // 1s default timeout\n\n// after\nresp, err := app.Test(req, fiber.TestConfig{Timeout: 5 * time.Second})","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"resp, err := app.Test(req, fiber.TestConfig{Timeout: 5 * time.Second})\nif err != nil {\n    if errors.Is(err, fiber.ErrTestGotEmptyResponse) {\n        // handler wrote nothing\n    } else if strings.Contains(err.Error(), \"failed to read response\") {\n        // malformed/truncated response from handler\n    }\n    return err\n}","preventionTips":["Raise TestConfig.Timeout for slow handlers (default is 1s).","Verify the handler emits a well-formed HTTP response (valid status, headers, body framing).","Confirm Content-Length / Transfer-Encoding match the body written."],"tags":["testing","http","response","test-helper"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}