## TL;DR

An intercept that never matches is almost always a pattern problem: wrong method, wrong path, or the request going to a different host. Log the actual requests in the Cypress network tab, copy the real method and URL, and match the pattern to reality.

## Error

```text
CypressError: Timed out retrying after 5000ms: `cy.wait()` timed out waiting 5000ms for the 1st request to the route: `getItems`. No request ever occurred.
```

## Steps

1. Open the failing run and look at the Cypress command log network entries (or the browser devtools in headed mode). Expected: you see the real requests the app made.
2. Compare method, path, and query string against your intercept. The most common miss is `cy.intercept('GET', '/api/items')` when the app calls `/api/v2/items?limit=20`. Expected: you spot the mismatch.
3. Fix the pattern with a glob or regex: `cy.intercept('GET', '/api/**/items*')`. Expected: the pattern matches the real request shape.
4. Define the intercept BEFORE the action that triggers the request. Expected: `cy.intercept(...)` appears above the `cy.visit()` or click in the test.
5. Re-run and confirm `cy.wait('@getItems')` resolves with the intercepted request visible in the log. Expected: the wait completes in well under the timeout.

## When to use

- `cy.wait('@alias')` times out with "No request ever occurred".
- You added or changed an intercept and the test broke.

## When not to use

- The request fires but the stubbed response is wrong (check the StaticResponse, not the pattern).
- GraphQL requests that batch multiple operations into one call (match on operation name in the body).

## Tool compatibility

- Cypress 10 through 14; `cy.intercept` replaced `cy.route` in Cypress 6+.

## Variant phrasings

### No request ever occurred for route

The pattern matched zero requests; the app either did not call it or called a different URL.

### cy.wait() timed out waiting for the 1st request

Same failure from the wait side; debug the intercept pattern first.

## Why it happens

Intercepts match on method plus a minimatch URL pattern. Apps change endpoints, add version prefixes, or append query params, and the old pattern silently stops matching.

## Edge cases

- `cy.intercept()` does not catch `fetch` calls made before the intercept was registered; order matters.
- Requests to a different origin need the full URL in the pattern, not just the path.
- GraphQL: match with a function on `req.body.operationName` instead of the URL.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_r4zVElJv-4bp5KCRiNkTJA
