Run Web Automation Tests at Scale with Agentic AI

Generate tests with AI agents or automate test suites with Selenium, Playwright and other frameworks. Run tests in parallel on TestMu AI scalable cloud grid.

Cypress Testing

Cypress Flaky Tests: Causes, Retries and Fixes (2026)

Cypress flaky tests come from fixed waits, late intercepts and broken retry-ability. Learn how Cypress retries work, reproduce the flake and fix it with code.

Published on:

Cypress tests flake mostly from fixed cy.wait(ms) calls, network intercepts registered too late, and commands that break retry-ability. Cypress doesn't retry failed tests by default; set retries: { runMode: 2, openMode: 0 } in cypress.config. A test that passes on retry is flaky: log it, give it an owner, and fix the cause.

This guide covers Cypress 16.2.1, the latest release on npm at the time of writing (published 28 October 2026). TestMu AI (formerly LambdaTest) runs Cypress suites as they are, so every fix here works in the setup you already have. New to the framework? Start with the Cypress tutorial, and for the wider picture on causes and policy, see the flaky test guide.

Why Are Cypress Tests Flaky?

Cypress tests flake when a command runs before the app is ready. The usual causes are fixed waits, intercepts registered after the request, and assertions that run once instead of retrying.

The Cypress documentation lists the race conditions behind most unreliable tests: animations, API calls, test server or database availability, resource dependencies and network issues, all covered in its test retries guide. Patterns in your own test code turn those races into failures.

Fixed cy.wait(ms) Calls

A fixed wait is a guess about how long the app takes. Guess too short and the test fails on a slow run. Guess too long and every run pays for it. The Cypress best practices mark waiting for arbitrary time periods as an anti-pattern and recommend route aliases or assertions instead.

Intercepts Registered Late

An intercept only sees requests sent after it is registered. When the page fires a request while loading and cy.intercept() comes after cy.visit(), the request has already gone. The test then times out on cy.wait('@alias'), or passes only when the request happens to be slow. The Cypress intercept guide covers the full API.

Commands That Break Retry-ability

Queries and assertions retry. Actions and .then() callbacks run once. A check placed inside .then() sees whatever the DOM holds at that instant, so it passes on a fast run and fails on a slow one.

Shared State and Test Order

A spec that passes only after another spec has run is flaky by design. Cypress clears the page, cookies, local storage and session storage before each test, but server-side data and IndexedDB persist, so a test that reads a record an earlier test created fails when the order changes or the spec runs alone. The Cypress test isolation guide lists what is and is not cleared.

Slow Backends and Shared CI Runners

An API that answers quickly on a laptop can answer slowly on a busy CI runner, and every wait that guesses fails there first. Stub the response when the spec tests UI logic, and give a genuinely slow command its own timeout instead of raising the global one.

Detect and fix flaky tests with TestMu AI

How Do Cypress Test Retries Work?

Cypress does not retry failed tests by default. Set retries with runMode and openMode, and Cypress reruns a failed test up to that many extra times before it marks the test as failed.

Add the option to the Cypress config file. With runMode: 2, a test gets up to three attempts under cypress run, and openMode: 0 keeps cypress open strict while you write tests.

const { defineConfig } = require('cypress');

module.exports = defineConfig({
  retries: {
    runMode: 2,   // cypress run, used in CI
    openMode: 0,  // cypress open, used while you write tests
  },
});
SettingDefaultWhat it does
retries.runMode0Extra attempts for a failed test under cypress run.
retries.openMode0Extra attempts for a failed test under cypress open.
retries: 2NoneOne number that applies to both modes.
{ retries: ... } on a test or suiteInherits configOverrides the config for one it() or describe().
it('allows user to login', { retries: { runMode: 2, openMode: 1 } }, () => {
  // ...
});

A retry reruns the test from the start, including its beforeEach and afterEach hooks. Failures in before and after hooks do not trigger a retry. Each failed attempt keeps its own screenshot, suffixed with the attempt number, and Cypress.currentRetry returns the current attempt inside a test. Cypress also offers experimental retries, which let you set the conditions under which a test counts as passed or failed; the test retries guide describes them.

Use retries to measure flake, not to hide it:

  • runMode only - keep openMode at 0 so a flaky test fails while you are still writing it.
  • Low numbers - one or two extra attempts absorb a timing hiccup. A higher number mostly makes a broken test slower to fail.
  • Per-test overrides - add one only with a comment that names the reason and the owner, so it does not outlive the fix.

Retry-ability vs Test Retries

Retry-ability and test retries solve different problems. Retry-ability keeps one command from failing because the app is a moment behind. A test retry reruns everything after a failure has already happened.

Retry-abilityTest retries
What is retriedQueries such as cy.get() and .find(), with the assertions linked to themThe whole test, including its beforeEach and afterEach hooks
When it runsInside one test, on every query and assertionAfter an attempt fails
Default limit4 seconds (defaultCommandTimeout)0 retries
Effect on flakePrevents timing failuresHides a flake unless you track it

Per the Cypress retry-ability guide, non-query commands such as actions execute once. That is why the assertion belongs on the query chain. The Cypress should command guide lists the assertions you can chain.

// cy.get() and .should() are linked: Cypress re-queries until the assertion passes (4 seconds by default)
cy.get('#orders .order').should('have.length', 3);

// .then() runs once with whatever the DOM holds at that moment
cy.get('#orders').then(($ul) => {
  expect($ul.find('.order').length).to.eq(3);
});

Running Cypress Suites on TestMu AI

TestMu AI runs the Cypress suite you already have and does not replace Cypress. Automation Cloud is cloud test automation infrastructure with AI-native debugging, which gives a flaky spec a controlled place to run and leave evidence behind:

  • Your existing specs - Cypress, Selenium, Playwright and Puppeteer scripts run as they are, with no rewrite and no proprietary test format.
  • Browser and OS coverage - 3,000+ browser and OS combinations are hosted for you, so a flake that appears on one configuration can be reproduced there.
  • Parallel execution - sessions run concurrently across configurations instead of one after another.
  • Artifacts on every run - network logs, console logs, video, screenshots and command logs are captured automatically, so a failed attempt keeps what the page and the network did.
  • AI-native triage and root cause analysis - network, console and framework logs are correlated to localize the likely cause of a failure. Treat it as a lead to verify, not a verdict.
  • LT Tunnel - specs can run against a local, staging or privately hosted app through an encrypted tunnel, with no public URL.

Moving a suite to the cloud does not fix a timing bug in the test. The fixes below still apply, and the cloud supplies the parallel capacity and the evidence to show they hold.

Note

Note: Run your Cypress suites with logs, video and screenshots on every run. Try TestMu AI Today

Reproducing a Flaky Test

A flake you cannot reproduce is a flake you will retry forever. These steps make a timing flake fail on demand:

  • Set retries to 0 for the spec, so a flaky attempt shows up as a failure instead of a pass on retry.
  • Repeat the test inside one spec. Cypress._.times() generates as many copies as you need.
  • Slow the response. A one second delay on the request exposes any test that guesses at timing.
  • Run in the browser and with the same flags as CI, then open the failed attempt in Cypress debugging tools to see what the DOM held.
// Twenty copies of the same test in one spec, with retries left at 0
Cypress._.times(20, (i) => {
  it('orders load, run ' + (i + 1) + ' of 20', () => {
    cy.intercept('GET', '/api/orders').as('orders');
    cy.visit('/');
    cy.get('#load').click();
    cy.wait('@orders');
    cy.get('.order').should('have.length', 3);
  });
});
// Slow the response by one second to expose a test that guesses at timing
cy.intercept('GET', '/api/orders', (req) => {
  req.on('response', (res) => res.setDelay(1000));
});

Timings differ for every app, so run the repeated spec against your own app before and after each fix. A spec that passes all twenty copies with retries at 0 is a stronger signal than one green run.

Detecting Flaky Specs in CI

Detect flaky Cypress specs in CI by tracking every test that fails and then passes on retry. Cypress Cloud flags those tests, and HyperExecute adds muting and automatic retries on top.

Cypress Cloud

With runs recorded to Cypress Cloud, the Test Results tab has a Flaky filter that shows tests that retried and then passed. The same tests carry a Flaky badge on the Latest Runs and Run Details pages. Test Case History shows the failed attempts with their screenshots and errors, plus the flake rate for the test. The Flake Detection and Flake Alerting features are described in the Cypress Cloud flaky test management guide.

HyperExecute

TestMu AI runs Cypress on HyperExecute, its AI-native test orchestration cloud, so the same specs run in parallel with intelligent test splitting and no changes to the specs. For flaky specs it adds two controls:

  • Test muting - mute a test from the three-dot menu on its result, or turn on automatic muting (the default threshold is 5 consecutive failures). A muted test stays inactive until someone unmutes it, so an unreliable test stops blocking the build while its owner fixes it.
  • Automatic retries - set retryOnFailure and maxRetries (1 to 5, default 2) in the YAML file and HyperExecute reruns a test command that fails with a non-zero exit code, which absorbs transient failures without touching your specs.

The setup steps are in the Cypress integration with HyperExecute guide, and the muting settings are in the HyperExecute test muting guide.

Test Insights

One run cannot show which specs flake. The consistently failing tests view in Test Insights ranks tests by how often they fail across the run history, so the chronic offenders become a fix list. It surfaces candidates for a person to fix, and it needs enough runs to count.

A Test That Passes on Retry

A green build after a retry still hides a flaky test. Treat every retried pass as a defect with three steps:

  • Log it. Keep the list of tests that needed a retry, from Cypress Cloud or your CI report.
  • Give it an owner, so one person is responsible for the fix.
  • Fix the cause with a deadline. A muted or quarantined test that nobody fixes is a test you no longer have.
Run tests up to 70% faster on the TestMu AI cloud grid

Fixes With Before/After Code

Each fix below replaces a guess with a condition. Apply them one at a time and rerun the repeated spec from the previous section after each change.

1. Replace a Fixed Wait With a Request Alias

Before, the test waits half a second and checks once. After, it waits for the request itself and then asserts on a query that retries.

// Before
cy.get('#load').click();
cy.wait(500); // a guess about how long the API takes
cy.get('#orders').then(($ul) => {
  expect($ul.find('.order').length).to.eq(3);
});
// After
cy.intercept('GET', '/api/orders').as('orders');
cy.get('#load').click();
cy.wait('@orders'); // continues when the request finishes
cy.get('.order').should('have.length', 3);

2. Register the Intercept Before the Page Loads

Register cy.intercept() before cy.visit() or before the click that sends the request. Otherwise the alias never matches.

// Before
cy.visit('/onload');
cy.intercept('GET', '/api/orders').as('orders'); // the request has already been sent
cy.wait('@orders');
// After
cy.intercept('GET', '/api/orders').as('orders'); // registered first
cy.visit('/onload');
cy.wait('@orders');
cy.get('.order').should('have.length', 3);

3. Move the Check From .then() to .should()

Use .should() for assertions on the page. Keep .then() for code that must run once, such as reading a value into a variable.

// Before
cy.get('#load').click();
cy.get('#orders').then(($ul) => {
  expect($ul.find('.order').length).to.eq(3); // runs once, cannot wait
});
// After
cy.get('#load').click();
cy.get('#orders .order').should('have.length', 3); // retries until it passes

4. Reset State Before Each Test

Create the data a test needs inside that test's own setup, so it passes alone and in any order. The seeding calls below stand in for your app's own API or a cy.task() that talks to your database.

// Before: the second test needs the order the first test created
it('creates an order', () => {
  cy.visit('/');
  cy.get('#add-order').click();
});
it('lists the order', () => {
  cy.visit('/orders');
  cy.get('.order').should('have.length', 1); // fails when run alone or out of order
});
// After: every test seeds its own data
beforeEach(() => {
  cy.request('POST', '/api/test/reset');
  cy.request('POST', '/api/orders', { item: 'book' });
});

it('lists the order', () => {
  cy.visit('/orders');
  cy.get('.order').should('have.length', 1);
});

5. Stub the Backend and Time the Slow Command

When a spec tests how the UI renders data, serve that data from a fixture so a slow or changing backend cannot fail it. When a command is genuinely slow, pass { timeout } to that command and leave the global timeout alone.

// Before: depends on the real API and its response time
cy.visit('/');
cy.get('.order', { timeout: 1000 }).should('have.length', 3);
// After: a fixture answers the request, and the slow report gets its own timeout
cy.intercept('GET', '/api/orders', { fixture: 'orders.json' }).as('orders');
cy.visit('/');
cy.wait('@orders');
cy.get('.order').should('have.length', 3);
cy.get('#monthly-report', { timeout: 15000 }).should('be.visible'); // this command is slow by design

To start, set retries: { runMode: 2 } in CI, list every spec that passes only on retry, and apply these patterns to the first one. The Cypress best practices guide covers selectors and the rest of a stable suite, and running Cypress with GitHub Actions covers the CI side. To validate the fundamentals, the free Cypress 101 certification from TestMu AI includes a hands-on coding assignment.

Author

...

Sri Harsha

Blogs: 8

  • Linkedin

Sri Harsha is Engineering Manager of the Open Source Program Office at TestMu AI, where he leads open-source engineering behind the Selenium and Appium automation grid and builds agentic AI systems for quality engineering. He is a member of the Selenium Technical Leadership Committee and a committer to WebdriverIO and Appium, and was recognized with the LambdaTest Delta Award 2023 for Best Contributor in open-source testing. He brings over 10 years of experience in software testing and automation, with earlier roles at EPAM Systems and ZenQ. Sri Harsha holds a B.Tech in Computer Science from Jawaharlal Nehru Technological University.

Reviewer

...

Himanshu Sheth

Reviewer

  • Linkedin

Himanshu Sheth is the Director of Marketing (Technical Content) at TestMu AI, with over 8 years of hands-on experience in Selenium, Cypress, and other test automation frameworks. He has authored more than 130 technical blogs for TestMu AI, covering software testing, automation strategy, and CI/CD. At TestMu AI, he leads the technical content efforts across blogs, YouTube, and social media, while closely collaborating with contributors to enhance content quality and product feedback loops. He has done his graduation with a B.E. in Computer Engineering from Mumbai University. Before TestMu AI, Himanshu led engineering teams in embedded software domains at companies like Samsung Research, Motorola, and NXP Semiconductors. He is a core member of DZone and has been a speaker at several unconferences focused on technical writing and software quality.

Cypress Flaky Tests FAQs

Did you find this page helpful?

More Related Blogs

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests