Deciding When and How to Enable Cypress Test Retries
A decision guide for enabling Cypress test retries: compare CI‑only vs. dev‑mode strategies, see a ready‑to‑use config, and learn how to validate retries without masking real failures.
18 Apr 2026, 02:43 UTC

The Decision
Flaky end‑to‑end (E2E) and component tests waste CI minutes and erode confidence. Cypress offers built‑in retries, but turning them on indiscriminately hides real defects and inflates run time. The decision is: enable a small, CI‑only retry budget for known‑flaky suites while keeping interactive runs fast and transparent.
Constraints That Shape the Choice
- CI budget – each retry multiplies machine minutes, especially with
--parallel. - Feedback speed – developers need instant results in
openMode; retries there slow debugging. - Root‑cause visibility – retries mask systemic issues (race conditions, state leakage) if used as a blanket fix.
- Test type – E2E and component tests share the same retry API since Cypress 12, but their flakiness profiles differ.
Supported Options at a Glance
| Strategy | runMode (CI) | openMode (Dev) | Typical Use | Risk |
|---|---|---|---|---|
| No retries | 0 | 0 | Strict pipelines, high‑confidence suites | All flakes surface immediately |
| CI‑only low retries | 1‑2 | 0 | Most projects; mitigates transient network/timing flakes | May hide occasional real failures if set too high |
| CI‑only higher retries | 3‑5 | 0 | Legacy suites with many external dependencies | Significant CI time increase; masks systemic bugs |
| Per‑test override | per‑test config | per‑test config | Targeted fix for a single flaky spec | Requires maintenance; easy to forget |
| Both modes enabled | 1‑2 | 1‑2 | Reproducing a flake locally | Slows interactive debugging; not recommended as default |
Trade‑offs
Retries only re‑run the test body (it/describe callback). before/after hooks execute once per suite, while beforeEach/afterEach run on every retry. This means state set up in beforeEach is refreshed, but any global side‑effects from before persist across retries.
Enabling retries in openMode adds latency to every test run in the Cypress UI, turning a 2‑second test into a 6‑second wait when a retry triggers. Keep openMode: 0 unless you are deliberately reproducing a flake.
Parallel execution (npx cypress run --parallel) multiplies the retry cost across machines. A suite with runMode: 2 on 4 machines can consume up to three times the baseline minutes.
Concrete Configuration
Add a retries object to each testing type in cypress.config.ts. The example below follows the “CI‑only low retries” strategy.
import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
retries: {
runMode: 2, // CI: retry up to two times
openMode: 0 // Dev: no retries
},
// other e2e settings…
},
component: {
retries: {
runMode: 1, // Component tests are usually faster; one retry is enough
openMode: 0
}
}
});
Override a single spec or test when you need a different budget:
// cypress/e2e/flaky-login.cy.ts
it('logs in with SSO', { retries: { runMode: 3, openMode: 0 } }, () => {
cy.loginViaSSO();
cy.url().should('include', '/dashboard');
});
Validation Steps
- Confirm version – component‑test retries require Cypress ≥ 12.0.0.
npx cypress --version # Expected: 12.x.x or higher - Run a known‑flaky spec with retries disabled to see the baseline failure.
npx cypress run --spec 'cypress/e2e/flaky-login.cy.ts' --config retries.runMode=0 # Expect: test fails on first attempt - Run the same spec with the CI retry config and watch the reporter.
npx cypress run --spec 'cypress/e2e/flaky-login.cy.ts' --config retries.runMode=2 # Reporter shows lines like: # Retry #1/2 # Retry #2/2 # ✓ logs in with SSO (after 2 retries) - Collect retry metrics over time using JUnit XML or Cypress Cloud.
npx cypress run --reporter junit --reporter-options mochaFile=results/[hash].xml # Parse the elements for count or use Cypress Cloud “Flaky Tests” dashboard.
Limitations & Checks
- Retries do not re‑run
before/afterhooks. If a flaky failure originates in suite‑level setup, retries will not help. - Uncaught application exceptions (e.g., a JS error in the app) may not trigger a retry depending on error type; verify with a forced error test.
- High retry counts combined with
--parallelcan exceed CI minute quotas. Monitorcypress runduration after enabling retries. - Prefer deterministic fixes (
cy.interceptfor network stubbing,cy.sessionfor auth caching, strictbeforeEachcleanup) over blanket retries.
Quick Decision Checklist
- ☐ Identify flaky specs via Cypress Cloud or JUnit history.
- ☐ Apply
runMode: 1‑2globally; keepopenMode: 0. - ☐ Add per‑test overrides only for specs that still fail after global retries.
- ☐ Track retry frequency weekly; retire retries when flakiness drops to zero.
- ☐ Budget CI minutes:
baseline_minutes × (1 + runMode)per parallel machine.
By constraining retries to CI, limiting the count, and measuring their impact, you gain resilience against transient failures without sacrificing debug speed or hiding deeper problems.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.