Q24 of 48 · Cypress
How does Cypress retry failed tests, and what config options control this?
Short answer
Short answer: Cypress retries failed *tests* (not just commands) when configured via `retries`. Default is no retry; `{ runMode: 2, openMode: 0 }` is a common setting that retries up to twice in CI and never in interactive mode. Retries should mask flake while you fix it, not be a permanent crutch.
Detail
Two distinct retry mechanisms exist in Cypress:
Command retry-ability — Cypress automatically re-runs query commands and assertions for up to
defaultCommandTimeout(4s by default). This isn't configurable per-test because it's the core mechanism.Test retry — when an entire test fails, Cypress can re-run it from
beforeEach. This is whatretriesconfig controls.
The retries setting accepts a number or an object:
// Same retry count for both modes
retries: 2
// Per-mode override
retries: {
runMode: 2, // CI / cypress run
openMode: 0, // local cypress open — never retry, see flakes immediately
}
Per-test override:
it('flaky network call', { retries: { runMode: 3 } }, () => { ... });
The opinionated take: retries are a temporary mitigation, not a strategy. If a test passes only on retry 2, the underlying flake is still there — and a real bug masked as flake will pass eventually too. The right workflow is:
- Allow retries in CI to keep the team moving.
- Track which tests retry (Cypress Cloud or a custom reporter).
- Treat consistent retriers as bugs to fix, not "just flaky tests."
Setting openMode: 0 is critical — locally you want to see flakes immediately, not have them hidden by retries.
// EXAMPLE
cypress.config.ts
import { defineConfig } from 'cypress';
export default defineConfig({
retries: {
runMode: 2, // up to 2 retries in CI
openMode: 0, // never retry locally — surface flake immediately
},
e2e: {
setupNodeEvents(on, config) {
// Track retries via afterSpec / Cypress Cloud
return config;
},
},
});
// Per-test override (use sparingly, with a TODO to fix root cause)
it(
'handles a known-flaky third-party widget',
{ retries: { runMode: 3 }, defaultCommandTimeout: 10000 },
() => { /* ... */ },
);