---
name: cargo-tests-failfast-hides-the-tail
description: "`cargo test --tests` STOPS after the first failing test BINARY, so every suite alphabetically after it never runs — the log ends and reads as if the sweep completed. Use --no-fail-fast."
metadata:
  node_type: memory
  type: feedback
---

`cargo test -p <crate> --tests` runs one binary per integration file and **halts the whole
invocation at the first binary that fails**. The suites after it — alphabetically — are never
executed, and **nothing in the output says so**. The log simply ends. There is no "skipped", no
count of unrun binaries, no non-zero tally distinguishing "3 failed" from "3 failed and 40 suites
never started".

**Measured 2026-08-19 (todlando, releases#170).** A sweep died in `attach_resize_capture` (a missing
fixture binary, not a real failure). I read the four reds it reported and started classifying them —
while `wanmsg.rs`, `inject_control_wedge.rs` and every other suite after `a…` had never run. The
change under test was a **message-delivery** change: the suites that actually covered it were in the
unrun tail. Re-running with `--no-fail-fast` surfaced two more failing suites the first run had
never reached.

**Why it is a silence trap and not a mere inconvenience:** the failure it hides is on the SAME side
as the failure it shows, so the visible reds feel like the complete picture and invite exactly the
wrong next move — triaging the four you can see instead of asking what did not run. It is the
[[gate-filters-read-as-absent]] shape at the binary level: a filter you did not know you applied.

**How to apply.** For any sweep whose purpose is COVERAGE (a pre-gate leg, a regression check, "is
anything else broken"), pass `--no-fail-fast` — the fail-fast default is for a tight edit loop,
where stopping early is the point, and it is the wrong default the moment you are trying to
establish that nothing else moved. Then reconcile: count the `test result:` lines against the number
of test binaries the crate has. If those two numbers disagree, your sweep is incomplete no matter
what the visible results say.

**And the companion, same session, same crate:** a *precondition* failure reads exactly like a
product failure. Three reds in `attach_resize_capture` were `prebuild the fixture binary: cargo
build -p mock-adapter --bin capture-player` — the test saying its rig was not set up. Building the
fixture turned them 5/5 green with no product change. Read the panic MESSAGE before classifying a
red; a suite that names its own missing precondition is not evidence about your diff.

Related: [[daemon-lib-tests-deadlock-on-live-host]] (the other "is this red mine?" trap on this
box), and the general discipline in [[dont-take-a-diagnosis-as-measured]].


---

**⚠ NEXTEST FAIL-FASTS TOO — 2026-08-27 (todlando, IO-PARSER W1).** The entry above says
`cargo test --tests`; the default is the same under `cargo nextest run`, and the failure mode is
one step subtler because nextest is *more* honest and still misleads.

`cargo nextest run -p spt-proto -p spt-daemon` hit 3 reds and printed:

```
  Cancelling due to test failure: 15 tests still running
     Summary [  21.210s] 750/1194 tests run: 747 passed (4 leaky), 3 failed, 0 skipped
```

Nextest DOES say it cancelled — cargo says nothing at all. But the line a reader carries forward
is the **Summary**, and `750/1194 tests run … 0 skipped` reads as a completed sweep with three
victims. The 444 tests that never started are not "skipped" by nextest's accounting, so the one
number that would falsify the reading is absent from the line that gets quoted. I nearly reported
"3 reds, rest green" — the rest had not run.

**How to apply:** `--no-fail-fast` on nextest too, for any sweep whose purpose is coverage. And
read the RATIO in the Summary, not the pass count: `750/1194` is the whole finding, and a sweep
whose numerator is under its denominator has not measured a population no matter what `0 skipped`
says beside it.
