A Cypress wait fails: 'timed out waiting 5000ms for the 1st request to the route'. What does that mean?
answer
- Two phases, two different clocks
- The wording says which one expired
- 5000 is the request-side default
- 30000 covers the server answering
- requestTimeout and responseTimeout are separate options
basics
~20 sThe request phase timed out: no request matching that aliased route left the browser inside requestTimeout, which defaults to 5000 ms. The app never made the call, so widening responseTimeout changes nothing about this failure.
solid answer
~40 s`cy.wait()` on a route alias runs **two** waiting periods, and the error names which one expired. The first waits for a matching request to leave the browser and is governed by `requestTimeout` (default `5000` ms); the second waits for the answer and is governed by `responseTimeout` (default `30000` ms). `5000ms ... for the 1st request` therefore means the app never issued the call — the route was registered but nothing matched it. Check whether the action that triggers the fetch actually ran, whether the app debounces or gates the call, and whether the request goes somewhere the route does not cover. A `30000ms ... for the 1st response` error is the opposite: the request went out and nothing answered. Widen the right one with `cy.wait('@getForecast', { requestTimeout: 15000 })` rather than a blanket `timeout`.
go deeper
Learn to read the phase word in the message. 'request' means the call never went out; 'response' means it went out and nothing came back. The two lead to different files.
Explain the two clocks and their defaults, and that a blanket timeout option sets both because requestTimeout and responseTimeout fall back to it when not given individually.
Walk an interviewer through the diagnosis: confirm the trigger ran, check for debouncing or gating, check the request really matches the route, and only then consider the budget.
Be ready to say which of the two budgets a team should ever override and where — per wait, or in the Cypress configuration — so a project's declared defaults still describe its real traffic.
## Two clocks, not one `cy.wait()` on a route alias is not a single timer. It runs **two waiting periods back to back**, and the error text tells you which one expired. 1. **The request phase.** Cypress waits for a request that the aliased route matches to leave the browser. This period is governed by `requestTimeout`, which defaults to `5000` ms. 2. **The response phase.** Once Cypress has seen a matching request begin, it switches clocks and waits for the response. This period is governed by `responseTimeout`, which defaults to `30000` ms. The split exists so you get fast feedback when a call never happens and a generous budget when a real server is being slow. A five-second wall on "did the app even ask?" and a thirty-second wall on "did the server answer?" are very different questions, and Cypress does not average them. ## Reading the error line | Error text | Which clock expired | What it means | |---|---|---| | `timed out waiting 5000ms for the 1st request to the route` | `requestTimeout` | No matching request left the browser at all | | `timed out waiting 5000ms for the 2nd request to the route` | `requestTimeout` | One request happened, a second never did | | `timed out waiting 30000ms for the 1st response to the route` | `responseTimeout` | The request went out; nothing answered it | Note the two variables in the message: the **ordinal** tells you which recorded request the wait was after, and the word **request** or **response** tells you which phase stalled. Both are more informative than the millisecond number, which most readers latch onto first. ## When the request phase expires A `... for the 1st request ...` failure is not a slow-network problem. Nothing matching your route ever went out. Work through the causes in this order: 1. **Did the triggering action run?** The command before the wait may have failed to click, or clicked a control that was still disabled while the dashboard hydrated. 2. **Does the app gate or debounce the call?** A station selector that only fetches on a real change event, or a search field that debounces, may simply not have fired inside the window. 3. **Does the request actually match the route you registered?** A call to a different host, a different method, or a path with a version prefix you did not account for goes out invisibly to the alias, which sees nothing and waits. 4. **Was the intercept registered before the request happened?** A route registered after the page already fetched has nothing to match. ## When the response phase expires A `... for the 1st response ...` failure is the opposite picture and a much shorter list: the request left the browser and no response came back inside `responseTimeout`. Either the backing service is genuinely hanging, or a stub handler that was supposed to reply never did. This is the failure where widening a budget is sometimes legitimate, because the app is behaving and the dependency is slow. ## Putting the timeout in the right place The options object on `cy.wait()` carries three relevant keys, and they are not interchangeable: - `{ requestTimeout: 15000 }` — widen only the wait for the request to go out. - `{ responseTimeout: 60000 }` — widen only the wait for the answer. - `{ timeout: 15000 }` — becomes the **default for both**, because `requestTimeout` and `responseTimeout` each fall back to `timeout` when not given individually. A blanket `timeout` of `15000` therefore *shortens* the response budget from thirty seconds to fifteen, which is rarely what the author intended. You can also move the defaults for a whole project by setting `requestTimeout` and `responseTimeout` in the Cypress configuration, and read the effective values at runtime with `Cypress.config()`. ## What does not govern this wait `defaultCommandTimeout` is a frequent wrong answer. It governs most other commands and the retrying assertions chained after a query — it does **not** set either of `cy.wait()`'s alias phases. Raising it to fix a wait timeout changes nothing and leaves a misleading configuration behind. ## The habit worth having Read the phase word before you read the number. A request-phase failure sends you into the application and the route definition; a response-phase failure sends you into the service or the stub. Two-thirds of the debugging time people spend on this error is spent on the wrong side of that line, and the message told them which side it was on.
- In Cypress, what does `{ timeout: 20000 }` on `cy.wait('@getForecast')` actually change?It becomes the default for *both* phases, because `requestTimeout` and `responseTimeout` each fall back to `timeout` when not supplied individually. So a blanket `timeout` of twenty seconds also shortens the thirty-second response budget. Pass `{ requestTimeout: 20000 }` when you only mean to widen the request side.
- Why does raising `responseTimeout` rarely fix a 'no request ever occurred' Cypress failure?Because the wait never reached the response phase. `responseTimeout` only starts once Cypress has seen a matching request begin. If nothing matched, the cause is in the application or in the route definition, and the only clock that governed it was `requestTimeout` — widening the other one just makes the same failure take longer to appear.
saying these in an interview costs you the question
- Treats requestTimeout and responseTimeout as one setting
- Raises defaultCommandTimeout to fix a wait timeout
- Reads 'no request ever occurred' as a slow server
- Assumes the default request budget is 30 seconds
- Blames the network before checking the trigger ran