cypress: XHR requests are cancelled and re-issued if they don't return in 30 seconds

Current behavior:

When an XHR request takes more than 30 seconds to complete, Cypress cancels the request and issues it again. Depending on what the server does with those requests, this can cause all sorts of problems (e.g. creating duplicate things, or directly resulting in failed tests when the server replies with a 5xx error that it wouldn’t have issued if the request hadn’t been sent twice).

Desired behavior:

Cypress should never retry an XHR request on its own, because it cannot know what the effects of a duplicate request could be.

Test code to reproduce

cypress-bug.zip (also contains the video generated by Cypress for the failing test).

I used the code in that zip file to generate the screen recording below. The idea is to set up a web server with an API call that takes 34 seconds to reply, then run a Cypress test that visits the home of the web server (which just issues an XHR call to the API method) and waits for the API response, with a timeout longer than the time it takes for the API to respond. You’ll see on the logs of the webserver that the API method gets called twice, the second one pretty much exactly 30 seconds after the first one.

To work with the code:

  • run npm i on both the webserver and tester folders
  • run node index.js from the webserver folder
  • once it’s running, npm run cypress from the tester folder

You’ll see that the webserver logs one call to /, one to /api, and ~30 seconds later another call to /api. Cypress then reports a failed test.

Versions

The issue happens starting with Cypress 3.8.0 (tested with 3.6.1, 3.7.0, 3.8.0, 4.0.1) Windows 10 Headless tests with Electron

Additional information

I originally discovered this with the Cypress Docker images. In the project where I found it I could even see Nginx reporting that the client (Cypress running tests) had closed the connection, right before receiving the duplicate request.

Screen recording of the code above showing the issue.

cypress retries request

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 4
  • Comments: 23 (10 by maintainers)

Most upvoted comments

@jennifer-shehane I think the part right before where you started the quote is also very relevant (emphasis mine):

and if the client is not directly connected to an HTTP/1.1 origin server, and if the client sees the connection close before receiving any status from the server, the client SHOULD retry the request

In this case the client is already “directly connected to an HTTP/1.1 origin server”, right? It sent the request and is only waiting for the server to reply. I can see why if the client has not yet established a connection to the origin server, and it sees a connection close, then it should retry the request, because it’s guaranteed that the server has not received it before. But once it established a connection with the server, I’d imagine that it should not retry a request that it already sent, no matter the kind of failure it sees (including a closed connection), otherwise the spec would be calling for potentially issuing POST requests to the server several times, which I’m not sure makes sense…

Besides that, note that the timeout I specified for Cypress in the repro was 35 seconds, so Cypress should not be aborting these requests at the 30 second mark, correct?

Have experienced this behavior as well on version 4.4.0 (likely older versions as well but was not caught until recent update) at both timeouts of 60 seconds and 25 seconds (after seeing this open issue). Requests are made exactly 60 or 25 seconds apart, respectively, after the timeout occurs when the test with the related XHR request fails.