skip to content

In Cypress, what do retries.runMode and retries.openMode control, and what are their defaults?

level: juniorimportance: should knowfreq 55%

answer

  1. Retrying is not on out of the box
  2. Two modes, two separate counts
  3. The number is not the total
  4. CI and the interactive App differ here
  5. Attempt zero is still an attempt

basics

~20 s

They set how many extra attempts Cypress gives a failing test: runMode applies to cypress run, openMode to cypress open. Both default to 0, so an unconfigured suite never retries a failing test at all.

solid answer

~40 s

`retries` is a Cypress configuration option that takes either a number or an object with `runMode` and `openMode`. Each value is a count of *additional* attempts, not the total, so `runMode: 2` allows up to three executions of a failing test under `cypress run`. Both default to `0`, which is why a suite that has never been configured reports the first failure and moves on. The two modes are separate because retrying pays off very differently: in CI it stops one intermittent test from blocking a pipeline, while in the interactive App a human is already watching, so most teams set `runMode` to 1 or 2 and leave `openMode` at 0. Only failures start a retry, and the last attempt decides the reported result.

go deeper

for a junior

Recall the shape of the option and its default: an object with runMode and openMode, both 0, counting extra attempts on top of the first run.

for a middle

Be ready to explain what a single attempt repeats - the test body with its beforeEach and afterEach hooks - and why suite-level hooks are outside that boundary.

for a senior

Expect to justify the number you picked for a real pipeline, and to say what evidence you would keep so a retried failure is still investigated rather than forgotten.

for a principal

Own the standard: who is allowed to raise the count, what has to be true before a test is retried at all, and how the team avoids treating retries as a permanent fix.

## What the `retries` option counts Cypress ships with test retries switched **off**. As of Cypress 16 the `retries` configuration option defaults to `{ runMode: 0, openMode: 0 }`: a failing test runs exactly once, is reported failed, and the run continues. When you do set it, the number is a count of **extra attempts**, never the total number of executions. - `retries: 2` — up to three executions of a failing test (the original attempt plus two retries), in both modes. - `retries: { runMode: 2, openMode: 0 }` — up to three executions under `cypress run`, exactly one under `cypress open`. - A **passing** test is never re-executed; only a failure starts a retry. - The **last** attempt decides the reported outcome. A test that fails twice and passes on the third attempt is reported as passed. ## Why `runMode` and `openMode` are separate keys `runMode` covers `cypress run`, the non-interactive execution CI drives. `openMode` covers `cypress open`, the interactive App you debug in. They are separate keys because a retry is worth very different amounts in the two places. | | `runMode` | `openMode` | |---|---|---| | Applies to | `cypress run` | `cypress open` | | Default | `0` | `0` | | Usual setting | `1` or `2` | `0` | | What a retry buys | a pipeline not blocked by one intermittent test | little — someone is already watching | | What a retry costs | wall-clock time and a weaker failure signal | several attempts to scroll back through | Because `retries` is one of the options that can be overridden per suite and per test, a single badly-behaved specification can be given its own count without loosening the whole project. ## What one attempt actually repeats An attempt is a fresh execution of the **test**, not of the spec file: 1. The Mocha `beforeEach` hooks that apply to the test, in declaration order. 2. The `it` body, from its first `cy` command. 3. The Mocha `afterEach` hooks, once the attempt ends. Mocha's `before` and `after` hooks are **not** repeated — they belong to the suite, not to the test — and a failure *inside* `before` or `after` does not trigger a retry at all. Cypress resets the browser between attempts the way it does between tests, but nothing outside the browser is rewound: whatever the failed attempt wrote to your backend is still there for the next one. ## Reading and recognising an attempt `Cypress.currentRetry` is a number readable inside a test or a test hook: `0` on the first execution, `1` on the first retry, and so on. It is `null` outside a test or hook, so it is not something to reach for in a plugin or at the top of a spec file. Failure artefacts are labelled as well — a screenshot taken on the second attempt gains an `(attempt 2)` suffix in its filename, so a folder of screenshots tells you which execution produced which image. ## Test retries are not the same mechanism as retry-ability Two different things get called "retrying", and the option only controls the second: - **Retry-ability** happens *inside* a test. Cypress re-runs linked queries and their assertions for up to `defaultCommandTimeout` so that a late render does not fail an assertion. It is on by default and it costs milliseconds. - **Test retries** happen *after* a test has already failed. Cypress re-executes the whole test from its first command. It is off by default and it costs a full test's worth of wall-clock time. The second is a far blunter instrument than the first, and it only begins where the first has already given up. When a failure gets absorbed by a test retry, the useful question is usually why the assertion inside the test could not retry its way to a pass — not how many test-level attempts to allow. ## What the option cannot decide for you Setting a count is easy; the consequences are the interesting part. - A retry does not remove a failure, it removes its **visibility** at the top level of the report. - The higher `runMode` climbs, the more reliably a genuinely broken test goes green, and that is exactly the test you most needed to see fail. - `openMode: 0` is the useful default precisely because you want a failure to sit still on screen while you look at it. - A retry can only cure a failure whose cause was transient and inside the browser — a render that arrived late, a response that was slow. A wrong selector, a real regression, or an effect the first attempt already committed fails identically on every attempt.

  • If retries is set to a plain number instead of an object, what happens?
    The single number is applied to both modes, so `retries: 1` gives a failing test one extra attempt in `cypress run` and one in `cypress open`. The object form exists so you can keep the interactive count at 0 while CI retries.
  • Does a retry re-run the whole spec file or just the failed test?
    Just the failed test, together with the Mocha `beforeEach` and `afterEach` hooks that apply to it. Other tests in the spec are untouched, and suite-level `before`/`after` hooks run once for the suite regardless of how many attempts a test takes.

saying these in an interview costs you the question

  • Thinks Cypress retries failing tests by default
  • Reads runMode: 2 as two total executions rather than three
  • Believes a retry re-runs the whole spec file
  • Sets the same high count for openMode and runMode without thinking
  • Assumes a failing before hook is retried like a test