Your parallel `cypress run --record` jobs land in Cypress Cloud as separate runs. Why?
answer
- One value has to be common
- Auto-detected, and sometimes wrongly
- Unique per build, identical per machine
- Pipeline id, or the commit SHA
- --ci-build-id needs --group or --parallel
basics
~20 sThey are not sharing a CI build id. Cypress ties machines into one run by a build id it auto-detects from the CI environment, so when that value differs per job each job opens its own run. Pass --ci-build-id explicitly.
solid answer
~50 sCypress joins several `cypress run --record --parallel` invocations into one Cloud run by a **CI build id**. It derives that id from a provider environment variable — Circle's `CIRCLE_WORKFLOW_ID`, GitLab's `CI_PIPELINE_ID`, Jenkins's `BUILD_NUMBER` and so on — and every machine has to arrive with the *same* value. Containers that each receive a fresh id, an unrecognised provider, or a re-triggered job all produce fragmented runs. The fix is to pass a value identical across machines and unique per build with `--ci-build-id`, usually the pipeline id or, failing that, the commit SHA. If Cypress can determine nothing at all it refuses outright, saying it could not automatically determine or generate a `ciBuildId`. Once the id is shared, `--group` labels the machines inside that run — and a group name must be unique in the run unless the machines sharing it also pass `--parallel`.
go deeper
Know that a parallel Cypress run needs every machine to share one build id, and that Cypress usually detects it from the CI environment without you passing anything.
Explain what --ci-build-id, --group and --tag each do, and why the build id must be identical across machines but different from one build to the next.
Read the actual failure: fragmented runs, an indeterminate ciBuildId, a duplicate group name, or a parameters mismatch each point at a different mistake in how the jobs were wired.
Decide the run shape your organisation reads results through — a group per package, per browser, or per environment — and make the build id deterministic across every repository that records.
## What actually glues machines into one run A recorded Cypress run is a Cloud-side object, and several `cypress run --record` invocations join it by presenting the same **CI build id**. That id is the only thing tying them together: not the branch, not the commit, not the group name. Machines that arrive with different build ids are, as far as the Cloud is concerned, different runs that happen to share a project. Cypress tries to work the id out for you from the CI provider's environment. It reads a build-identifying variable per provider — Circle's `CIRCLE_WORKFLOW_ID`, GitLab's `CI_PIPELINE_ID`, Jenkins's `BUILD_NUMBER`, Bitbucket's `BITBUCKET_BUILD_NUMBER`, Travis's `TRAVIS_BUILD_ID`, and similar ones for the other supported providers. When that guess is right, you never touch `--ci-build-id` at all. ## When the guess is wrong The guess fails in exactly the situations that produce fragmented runs: - A **custom or containerised setup** the provider list does not cover, so nothing is detected. - A variable that is **unique per job rather than per build** — each container gets its own value, so six machines open six runs. - A **re-triggered job** that reuses the build id of a run that has already finished, so the new machines try to join a completed run. The fix is to pass a value that is *identical across every machine in the build* and *different from build to build*: `cypress run --record --parallel --ci-build-id $CI_RUN_ID`. A pipeline id is ideal; the commit SHA is a workable fallback as long as you never run the same suite twice against the same commit. Note that `--ci-build-id` is only accepted alongside `--group` or `--parallel` — on its own, Cypress tells you it is used to group or parallelise runs together and stops. ## The four errors you will actually meet 1. **"could not automatically determine or generate a ciBuildId"** — you passed `--group` or `--parallel` and Cypress detected no provider variable. Pass `--ci-build-id` yourself. 2. **"this group name has already been used for this run"** — two machines sent the same `--group` under one build id without `--parallel`. Either they are parallel workers and should say so, or they are separate slices and need different group names. 3. **"we do not parallelize tests across different environments"** — the machines share a build id but disagree on their environment parameters. Every machine in a parallel group must send identical `specs`, `osName`, `osVersion`, `browserName` and major `browserVersion`. A stray `--spec` filter on one job, or one runner image on a different browser build, is the usual cause. 4. **"already complete and will not accept new groups"** — a late machine tried to join after the run finished its completion delay. A run also refuses `--parallel` once it has been complete for more than 24 hours. ## What sharing a build id does not do Joining is decided when a machine starts, not afterwards. Nothing merges two runs that were already recorded separately, so a fragmented build is repaired by re-running with the right id, never by stitching results together in the Cloud. Joining also has a window: after the last known machine finishes, the run waits out a **run completion delay** — configurable per project and 60 seconds by default — before it is considered complete, and that wait is exactly what lets a group whose CI job started late still land in the same run. Once the window closes, a machine arriving with the same build id is told the run is already complete and will not accept new groups. ## `--group` and `--tag` are not the same tool | | `--group` | `--tag` | |---|---|---| | purpose | partitions machines *inside* one run | labels the whole run | | uniqueness | must be unique in the run, unless those machines also pass `--parallel` | free-form, repeatable | | needs a shared build id | yes | no | | typical value | `checkout`, `admin-portal`, `2x-chrome` | `nightly`, `staging`, `node-22` | Grouping does not require parallelisation and parallelisation does not require grouping; they compose. Tags are for the things Cypress does not record on its own — the environment a run hit, the Node.js version it used — so you can tell otherwise-identical runs apart in the Cloud. ## Getting it deterministic in a monorepo For a storefront monorepo the natural shape is one group per package, all under one build id: ```bash # CYPRESS_RECORD_KEY comes from the CI secret store BUILD="$CI_PIPELINE_ID" npx cypress run --record --parallel --ci-build-id "$BUILD" \ --group checkout --spec 'cypress/e2e/packages/checkout/**/*' ``` Each package's job passes its own `--group` and the same `--ci-build-id`, so the Cloud shows one run with three labelled groups instead of three unrelated runs. Machines inside a group parallelise against each other; the groups themselves stay distinguishable in the Machines and Timeline views when you are asking which package's specs cost you the wall-clock time.
- One Cypress machine reports that Cypress does not parallelize tests across different environments. What went wrong?That machine joined a parallel group whose environment parameters do not match the first machine's. Every machine in a parallel group must send identical `specs`, `osName`, `osVersion`, `browserName` and major `browserVersion`. The usual causes are one job carrying a `--spec` filter the others do not, a different runner image, or a browser that resolved to a different major version on one machine.
- When would you use `--group` without `--parallel` in a Cypress run?When you want several distinct slices reported under one run but each slice runs on a single machine — a group per browser, or a group per package in a monorepo. They still need a shared `--ci-build-id` to land in the same run, and each group name must be unique. Grouping and parallelisation compose but neither requires the other.
saying these in an interview costs you the question
- Thinks the branch or commit alone links machines into one run
- Uses a per-job variable as the ci-build-id
- Confuses --group with --tag
- Reuses one group name across machines without --parallel
- Expects Cypress to merge separate runs after the fact