Request Failed - EOF

Hi i am facing this error while running the test. There are some http request which are not reaching the server it seems since Http response status code recieved is 0. “Request Failed” error=“Post \“https://wwwpp.abc.com/PSQ1/works/Coach\”: EOF” What is EOF in this context. In general any http request can fail? Is this the expected behaviour from tool perspective? We have verified that application is stable and i am running with 1 vuser and 1 iteration. So its not even a load. Can someone help me with this ?

The error is caused by stale keep-alive connection. HTTP client of Go reuses connections from a pool by default and if the server closes the connection on its side due to idle timeout Go still tries to reuse it resulting in EOF and status 0

DisableKeepAlives:true(in the http.Client Transport config)
Every request gets a fresh TCP connection->no stale sockets
Timeout=> 30*time.second
important because without a timeout ,a dead connection hangs forever
dowithRetry() function
If a one-off EOF occurs it tries 3 times in 200ms instead of failing the test outright.


double check the url the pp looks like a typo if the hostname itself is wrong it will
not help because the connection will fail at DNS/TLS before any HTTP even happens → the url which you have posted

Hi @infofcc3 Thank you so much for taking some time to simulate the same behaviour and providing me the detailed info about the processes happening in the background. Apologies since the url’s are bit confidential i intentionally posted some wrong url just to illustrate the error. I have implemented the same solution by adding that config change within options and it is working fine. A small query here about this approach, What is the impact on e2e response time if we are forcing to establish the new socket connection every time for every http request, because there will be some time spent to establish the new connection every time which will get added to the e2e ? Could you please advise about this

For the e2e response time I compared both behaviors locally
KeepAlive ON
lower average latency due to connection reuse
but occasional stale socket reuse produced EOF


KeepAlive OFF
slightly higher response time
but stable request behavior with no EOFs observed
In low traffic scenarios like For 1 user performing
this latency increase is usually very small and often negligible compared to the stability improvement However, under higher request volume, disabling keep-alive completely can increase →
connection setup overhead,TLS cost,CPU usage and overall latency
So for production-grade optimization a better long-term approach is usually
keep keep-alives enabled, tune IdleConnTimeout / MaxIdleConns properly
add retry handling for transient EOF/network errors

Example
transport = &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 30 * time.Second,
}
So overall
DisableKeepAlives: true
is a very good stability/debugging workaround while
transport tuning plus retries is generally the better long term production solution.

hi @infofcc3 Thanks for the reply and extremely sorry for the late reply . But are we going to look for the issue so that tool will use the right connection from the pool not the stale connection. Because we can not establish connection every time ( by DisableKeepAlives to true ) which will have impact on latency for sure but it will be a huge burden on the application server during load testing since it will be a bigger volume and transactions which we will perform. also when it comes to retries to avoid this if it is a case of ui application testing we will have n number of different http calls so we dont know which http call will fail exaclty and for that we need to do retry. Also adding these additional checks for each and every http call will have additional computation which is unnecessary here and direct impact on the test scenarios could be like expected volume will not be achieved . So instead of all these work arounds cant we look for the solution on tool to handle this efficiently

Hi, yes, I agree with your concern. DisableKeepAlives: true was mainly useful as a workaround to confirm that stale pooled connections were involved; I wouldn’t recommend it as the long-term solution for load testing.

One important clarification: Go’s net/http Transport already removes a connection from consideration when it detects that the connection is dead. The limitation is the automatic retry policy. Go only retries a network error when the connection has already been reused and the request is considered idempotent/replayable. GET, HEAD, OPTIONS, and TRACE qualify automatically; requests carrying Idempotency-Key or X-Idempotency-Key can also qualify.

This is intentional because retrying a non-idempotent request such as POST can potentially execute the operation twice if the original request actually reached the server but the response was lost.
RFC 9110, Section 9.2.2 (Idempotent Methods) covers this →

So the key question is whether the mbe_blowers_i / Coach endpoint is safe to replay:

If it is idempotent/safe to repeat: using an Idempotency-Key (assuming the application supports that semantic) would allow Go’s transport to handle the retry without adding retry logic to every test request.

In that case, the better long-term solution would be to make the endpoint explicitly idempotent (for example, by supporting an idempotency key) rather than disabling keep-alives or blindly retrying all failed POSTs.

I agree that this should ideally be handled centrally rather than requiring users to add doWithRetry() around every HTTP call, but the tool also needs to preserve the semantics of non-idempotent requests.