Fix crash in after:spec when reloading after the last test - #1365
Fix crash in after:spec when reloading after the last test#1365PravinPatil17 wants to merge 2 commits into
Conversation
You're right — the feature test I first added passes on master; I've removed it. I had the wrong trigger. Here's the actual one, plus a deterministic reproduction you can run. The reload isn't hook-driven. It's a mid/late-spec Electron GPU/renderer crash (GPU process exited unexpectedly: exit_code=15) under memory pressure: Cypress recovers by re-firing before:spec after the last scenario already finished, so the state machine goes test-finished → has-reloaded, and since nothing re-runs (no specEnvelopes re-emitted), after:spec fires while still in has-reloaded and throws. This is field-confirmed on cypress@15.15.0 + preprocessor 24.0.1, on specs with >10 scenarios; all scenarios pass and the job only fails in afterSpecHandler. This is really the case the browserCrashExprCol guard already tries to cover — but that guard only matches We detected that the … process just crashed. A GPU-process crash recovered mid-spec leaves results.error as null by after:spec (all tests ultimately passed), so the guard is skipped and the switch throws. Since the crash isn't scriptable in a cucumber feature, I've added a handler-level test (lib/plugin-event-handlers.test.ts, gated to Cypress <15.18.0 where has-reloaded is reachable) that drives beforeRun → beforeSpec → specEnvelopes → testCaseStarted → testCaseFinished → beforeSpec (crash re-fire) → afterSpec → afterRun. It fails on master with the exact error and passes with this change, and asserts the completed scenario is preserved in the report. |
ec6ebaa to
ec4b8f2
Compare
Unfortunately, your test is nothing I'd like to add to this repository. It fails to test any Cypress behavior at all. It test's an assumption, something I can't verify. Nor does it catch any regression or improvement in current behavior.
Why don't you share a little bit about this? How can I reproduce the issue? |
Reload-behavior on Cypress <15.18.0 re-fires before:spec. When the reload
happens after every test body has already finished -- eg. a browser (GPU /
renderer) crash that Cypress recovers from by re-firing before:spec -- the
state machine enters "has-reloaded" but no test re-runs, so after:spec fires
directly. afterSpecHandler did not handle this state (nor its sibling
"has-reloaded-received-envelopes") and threw:
Unexpected state in afterSpecHandler: has-reloaded
which is surfaced to users as a misleading "some other plugin is overwriting
this plugin's event handlers" error.
Both states already carry the completed messages in `messages.current`, so
they now flow through the normal report-generation path -- the report is
preserved rather than thrown away.
Adds a handler-level regression test (gated to Cypress <15.18.0, the only
versions where "has-reloaded" is reachable) that drives the crash-recovery
sequence and asserts after:spec doesn't throw and the completed scenario is
preserved in the report. It fails on master and passes with this change.
Because the real-world trigger (a non-deterministic browser crash) can't be
scripted in a .feature, debug/repro-has-reloaded.js reproduces the exact
resulting event sequence against the compiled state machine for debugging.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
636f8b3 to
20fe235
Compare
i have added the repro readme please refer |
|
You're misunderstanding what I mean by a reproducible example. This still doesn't illustrate Cypress' behavior and it doesn't allow me to get a better understanding of the error. If I can't reproduce the behavior, then I can't fix it.
Can you share this field test that lets me observe the erroneous behavior? |
debug/repro-cypress/ is a minimal, drop-in Cypress project that reproduces the
after:spec has-reloaded crash in a real Cypress run. A crashMode env switch
covers two modes:
- cdp (default): real navigation + a deterministic GPU-process crash via CDP
(Browser.crashGpuProcess). Reliable on any machine.
- memory: self-contained heavy page that exhausts GPU memory with WebGL until
the GPU process crashes on its own -- the raw field scenario.
A GPU-process crash is used deliberately: renderer crashes are already caught by
afterSpecHandler's browserCrashExprCol guard, whereas a GPU crash slips through
to the unhandled has-reloaded state (field signature "GPU process exited
unexpectedly: exit_code=15").
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
have added repro project , can you please give it a try |
Reload-behavior on Cypress <15.18.0 re-fires before:spec. When the reload occurs once every test body has already finished (typically in an after() / afterEach() hook), the plugin enters a "has-reloaded" state but no test re-runs, so after:spec fires directly. afterSpecHandler did not handle this state (nor its "has-reloaded-received-envelopes" sibling) and threw:
which surfaced to users as a misleading "some other plugin is overwriting this plugin's event handlers" error.
Both states already carry the completed messages in
messages.current, so they now flow through the normal report-generation path instead of throwing.Adds a regression feature (gated to Cypress <15.18.0, where the state is reachable) plus an isPre15_18 helper and matching cucumber tag hook.