Skip to content

Cypress Flaky Tests: Retries, Detection & Fixes (2026)

Cypress tests flake from fixed cy.wait() calls, animations, and cross-test state. Fix with intercept-and-wait, isolation, and retries, then track flakiness.

İbrahim Süren
Founder · Jun 25, 2026 · 4 min read
Cypress Flaky Tests: Retries, Detection & Fixes (2026)

Cypress tests flake mostly from fixed cy.wait(ms) calls, animations, and state leaking between tests. Cypress queries and assertions already auto-retry, so the fixes are: wait on network aliases instead of time, rely on retry-ability instead of arbitrary waits, keep test isolation on, and enable test retries — then track which tests still flake across runs.

Key takeaways

  • Cypress queries and assertions already auto-retry — flakiness usually comes from bypassing that with cy.wait(time).
  • Wait on an intercepted network alias (cy.intercept + cy.wait('@alias')), not a fixed duration.
  • Keep test isolation enabled so state doesn't leak between tests.
  • Enable Cypress test retries in run mode to absorb residual flakiness.
  • Retries pass over the symptom; track flake history to find and fix the cause.

Cypress fights flakiness by design — queries and assertions automatically retry until they pass or time out. So flaky Cypress tests almost always trace back to something that defeats that retry-ability. This guide covers the usual culprits and their fixes. For the framework-agnostic view, see the complete guide to flaky tests. Where we reference Qualflare, we describe only what it actually does.

Why Cypress tests flake

Cypress’s retry-ability means most timing is handled for you — until you bypass it. The recurring causes, especially under the slower, busier conditions of CI versus local:

  • Fixed cy.wait(2000) waits that guess at timing and lose the race on a slow runner.
  • Animations and transitions that briefly delay elements.
  • State leaking between tests — leftover cookies, local storage, or server data.

All three introduce non-determinism — the outcome depends on timing the test doesn’t control.

The fixes

Replace cy.wait(time) with network aliases

The biggest win. Instead of guessing a duration, wait for the actual request:

// Flaky: guesses how long the request takes
cy.wait(2000);
cy.get('.results').should('be.visible');

// Stable: waits for the response, however long it takes
cy.intercept('GET', '/api/results').as('getResults');
cy.get('[data-test="search"]').click();
cy.wait('@getResults');
cy.get('.results').should('be.visible');

This is both faster (no over-waiting) and stable across environments.

Lean on retry-ability, not arbitrary waits

cy.get(...).should(...) retries the query and assertion together until they pass. Assert on the end state you expect rather than inserting waits before it — the assertion is the wait.

Keep test isolation on

Modern Cypress enables test isolation by default, resetting state between tests so one test’s leftovers can’t flake the next. Keep it on; if you disable it for a suite, you take on the burden of cleaning state yourself.

Handle animations

Elements mid-animation can be actionable-but-unstable. Cypress’s actionability checks catch most of this; for stubborn cases, disable CSS animations/transitions in the test environment.

Enable test retries

For residual flakiness, configure retries so CI stays unblocked:

// cypress.config.js
module.exports = defineConfig({
  retries: { runMode: 2, openMode: 0 },
});

Retries in runMode (CI) absorb intermittent failures without retrying during local development.

Detect flakiness over time

Flaky tests are common at scale — Google found almost 16% of its tests exhibit some flakiness (Google Testing Blog, 2016). Retries keep the build green, but a test that only passes on retry is still a flaky test — and the free Cypress runner won’t tell you which tests flake across runs over time. For that you need history-based detection: export Cypress results as JUnit or mochawesome and send them to an observability layer that scores reliability. See Cypress test reporting. Qualflare scores each test’s flakiness from its history and clusters related failures, so you fix causes instead of chasing symptoms.

Start free with Qualflare — send your Cypress results and get flaky scoring and a reliability trend, free to start.

Flaky tests in other frameworks: Playwright, pytest, and Jest & Vitest.

Frequently asked questions

Why are my Cypress tests flaky?

The most common causes are fixed cy.wait(milliseconds) calls that guess at timing, animations that delay elements, and state leaking between tests. Cypress queries and assertions already auto-retry, so replacing time-based waits with network-alias waits and keeping test isolation on removes most flakiness.

How do I stop using cy.wait with a fixed time?

Intercept the request and wait on its alias: cy.intercept(‘GET’, ‘/api/x’).as(‘getX’), trigger the action, then cy.wait(‘@getX’). This waits exactly until the response arrives instead of guessing a duration, which is both faster and stable across environments.

Does Cypress have built-in test retries?

Yes. You can configure retries in cypress.config (for example retries: { runMode: 2, openMode: 0 }), so a failing test is retried in CI. Treat retries as a way to stay unblocked while you fix root causes, not as a permanent fix — a test that only passes on retry is still flaky.

How do I detect which Cypress tests are flaky?

You need history across runs, not a single result. Export Cypress results (JUnit or mochawesome) and send them to a test observability tool that scores each test’s flakiness from its pass/fail history, so you can see and prioritize the worst offenders.

Ready to ship with confidence?

Start free with Qualflare's AI-powered test management.