bug: flaky e2e attachment restore/replace — write+reload round trip races the 10s WDIO timeout #39

Closed
opened 2026-11-02 07:07:25 +00:00 by Gilles · 0 comments
Owner

Intermittent timeouts in e2e/attachments.spec.ts, seen on run #96 (both supprime un fichier hérité puis le restaure and propose de remplacer un fichier du même nom failed the same way):

Error: Expect $(...attachment-row...).$(`.attachment-status...`).to be displayed
Expected: "displayed"
Received: "not displayed"

Root cause: in AttachmentList.vue, every write action (restore, confirmReplace, …) goes through settle(), which on success calls load() — this sets loading.value = true and briefly replaces the entire attachment list with a <p>Chargement…</p> placeholder while it re-fetches it (a second full network round trip after the write itself). The gap between the previous test's log line and the WDIO failure is ~10.07s — almost exactly waitforTimeout: 10000 in wdio.conf.ts — so this is a real timeout being hit, not a logic bug: the write+reload round trip occasionally takes longer than 10s.

The e2e job starts gunicorn with no --workers flag (package.json's test:e2e script), i.e. a single synchronous worker, serializing every request to the dev server during the test run. Production (Dockerfile) already runs --workers 3; the e2e job never got the same treatment. As the shared Forgejo runner (ci-base, used across 7+ repos) carries more concurrent CI load, this single-worker dev server increasingly can't keep up within the fixed timeout — matching the "happens more and more often, passes on retry" pattern.

Fix applied: give the e2e gunicorn --workers 2 (lighter than prod's 3, appropriate for a CI VM, but enough that the write and the list-reload aren't serialized behind each other or other traffic).

Not linked to a Thierryade spec: this is a CI/test-infrastructure fix, not a product-behavior change, and no existing spec covers e2e test-runner resourcing.

🤖 Found and fixed with Claude Code

Intermittent timeouts in `e2e/attachments.spec.ts`, seen on run [#96](https://git.stationmyr.net/thierryade/backend/actions/runs/96/jobs/1/attempt/1) (both `supprime un fichier hérité puis le restaure` and `propose de remplacer un fichier du même nom` failed the same way): ``` Error: Expect $(...attachment-row...).$(`.attachment-status...`).to be displayed Expected: "displayed" Received: "not displayed" ``` **Root cause**: in `AttachmentList.vue`, every write action (`restore`, `confirmReplace`, …) goes through `settle()`, which on success calls `load()` — this sets `loading.value = true` and briefly replaces the *entire* attachment list with a `<p>Chargement…</p>` placeholder while it re-fetches it (a second full network round trip after the write itself). The gap between the previous test's log line and the WDIO failure is ~10.07s — almost exactly `waitforTimeout: 10000` in `wdio.conf.ts` — so this is a real timeout being hit, not a logic bug: the write+reload round trip occasionally takes longer than 10s. The e2e job starts gunicorn with no `--workers` flag (`package.json`'s `test:e2e` script), i.e. a single synchronous worker, serializing every request to the dev server during the test run. Production (`Dockerfile`) already runs `--workers 3`; the e2e job never got the same treatment. As the shared Forgejo runner (ci-base, used across 7+ repos) carries more concurrent CI load, this single-worker dev server increasingly can't keep up within the fixed timeout — matching the "happens more and more often, passes on retry" pattern. **Fix applied**: give the e2e gunicorn `--workers 2` (lighter than prod's 3, appropriate for a CI VM, but enough that the write and the list-reload aren't serialized behind each other or other traffic). Not linked to a Thierryade spec: this is a CI/test-infrastructure fix, not a product-behavior change, and no existing spec covers e2e test-runner resourcing. 🤖 Found and fixed with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No description provided.