Skip to content

fix(flow-functionality): re-open the flow under test by id, not by name (#1336) - #1339

Merged
Victor-w-Madeira merged 1 commit into
mainfrom
fix/issue-1336-auto-save-off-reopen-by-id
Aug 6, 2026
Merged

fix(flow-functionality): re-open the flow under test by id, not by name (#1336)#1339
Victor-w-Madeira merged 1 commit into
mainfrom
fix/issue-1336-auto-save-off-reopen-by-id

Conversation

@Victor-w-Madeira

Copy link
Copy Markdown
Collaborator

Fixes #1336. Closes #1336.

Problem

The @stable manual-save test flaked on the 2026-07-22 and 2026-08-06 dailies with the same signature — locator.click: Timeout 45000ms exceeded re-opening "the just-created flow" through its list-card-open-button. 45 s on a card the test itself created is not a tight wait, and the product is fine here: the spec was driving another worker's flow.

reopenNewFlow clicked the first list-card whose name contained "New Flow". Langflow names every blank flow New Flow/New Flow (N), so under fullyParallel the list holds one per worker. Proved on nightly 1.12.0.dev18 by logging the page's own network:

POST /api/v1/flows/ -> 201   (8e767306)   ← bootstrap placeholder
POST /api/v1/flows/ -> 201   (ee8e0ab9)   ← the blank flow this test edits
...
NAV /flow/164b3c19-...                    ← the re-open, an id this page NEVER created
PATCH /api/v1/flows/164b3c19-... -> 404   ← its real owner's id-scoped cleanup got there first

With the save 404'd the editor never navigates back to the list, so the next re-open waits out its full 45 s on a card that has no reason to exist. That is exactly the CI artifact's state: the failure screenshot is the canvas, not the flows list, with the flow saved and those two 404s in the advisory log. Reproduced 3/8 at --workers=4 --retries=0.

Two further findings shaped the fix:

  • Selecting the card by id does not fix it. The flows list is paginated at 12 and ordered by updated_at DESC (pageSize = 12 in homePage, stmt.order_by(Flow.updated_at.desc()) in projects.py). Under load this test's own card is routinely off page 1 — measured at the failure: 12 of 12 slots taken by fresher flows. So the old spec's "success" depended on some other worker's blank flow being on top, which also made the discard assertion (div-generic-node count === 0) vacuous whenever it opened a stranger's fresh blank flow.
  • The id must be read after the blank-flow navigation. awaitBootstrapTest reaches the templates modal through the "New Flow" entry point, which parks the page on a placeholder flow that Langflow deletes as soon as the modal navigates elsewhere (flow-builder-welcome-mount.tsx). Reading page.url() before the click captures that placeholder — Create agent-tool-name-validation.spec.ts — invalid tool name blocked with clear message #490/Validate & promote flow settings — §12.2 #681 from the other side, and the first draft of this fix hit it.

Fix

  • Re-open by id (/flow/<id>), waiting for GET /api/v1/flows/<id> to resolve and the canvas to mount. Immune to pagination, ordering and to workers next door. The wait on the flow GET also stops the div-generic-node counts from reading a canvas that simply had not rendered yet.
  • Every exit now asserts the editor was left (expectLeftEditor). This is the attribution the flake lacked: a failed save leaves the editor in place, and that surfaced 45 s later as a card-click timeout naming neither the step nor the cause.
  • editorFlowId cross-checks the URL id against the ids this page created, so "the spec is driving somebody else's flow" fails where it happens instead of six steps later.
  • Quarantine lifted: test.fixme removed, @stable restored.

Rejected alternatives: keeping the card click scoped by the card's own id-scoped flow-name-<uuid> testid (does not survive pagination — the card is absent, not mis-selected); keying on the exact flow name (names are unique per user via UniqueConstraint("user_id", "name"), but the card is still off page 1); narrowing the list via its search box (adds a debounced server filter as a new failure surface to a spec whose subject is persistence).

Scope note

Every assertion in the test is unchanged in kind and strictly stronger in practice — the discard count, the two title-* visibility checks and the final count === 2 now run against the flow this test actually saved. The re-open is a full reload rather than an SPA route change, which proves server-side persistence more strictly; the "open a flow from its list card" path stays covered by the specs whose subject it is (bulk-actions, mcp-server).

Descriptive, out of scope: under an artificial 8× same-spec burst, POST /api/v1/flows/ and DELETE /api/v1/flows/ returned 500 ("An internal error occurred while creating the flow") — probable unique-name race. Never observed in serial execution.

Validation (nightly 1.12.0.dev18, --retries=0)

  • npm run typecheck ✅ · npx eslint <spec> ✅ (0 errors; 15 pre-existing style warnings)
  • 5/5 clean serial runs (--workers=1 --repeat-each=5, 55 s) ✅
  • 8/8 under the adversarial burst that produced 3/8 failures before the fix (--workers=4 --repeat-each=8), twice ✅
  • --trace=on ✅ (13 s, trace captured — this spec is not in the hanging family)
  • zero 🚨 Backend Error on the serial runs ✅
  • flow cleanup verified via GET /api/v1/flows/: 28 before → 28 after a run (zero leak); the pre-existing orphan was purged ✅
  • force-fail, executed:
    • expect(chatInputNode).toBe(0)toBe(1) ⇒ failed (Expected: 1, Received: 0)
    • expect(nodeCount).toBe(2)toBe(3) ⇒ failed (Expected: 3, Received: 2)
    • behavioral: PATCH /api/v1/flows/{id} forced to 500 ⇒ failed at expectLeftEditor on the second exit, not 45 s later on a card click
    • mutations reverted (grep FFMUT → 0 hits) + final green run ✅

Follow-up filed for the same hasText: "New Flow" hazard still present in mcp/server/mcp-server.spec.ts (lines 963, 1083).

…me (#1336)

The auto-save-off spec re-opened "the just-created flow" by clicking the first
`list-card` whose name contained "New Flow". Langflow names every blank flow
"New Flow"/"New Flow (N)", so under `fullyParallel` the list holds one per
worker and that filter routinely resolved another worker's flow. Proved on
nightly 1.12.0.dev18 by logging the page's own network: the page created
`8e767306` and `ee8e0ab9`, and the re-open landed on `164b3c19` — an id it
never created. When that flow's real owner ran its id-scoped cleanup, the save
PATCH came back 404, so the editor never navigated back to the list and the
next re-open burned its 45 s on a card with no reason to exist. That is the
2026-07-22 / 2026-08-06 daily signature, reproduced 3/8 at --workers=4.

Selecting the card by id does not fix it either: the flows list is paginated at
12 and ordered by `updated_at DESC`, and under load this test's own card is
routinely off page 1 (measured: 12 of 12 slots taken by fresher flows). So the
old spec's "success" depended on some other worker's blank flow being on top —
which also made the discard assertion (`div-generic-node` count === 0) vacuous
whenever it opened a stranger's fresh flow.

Re-open by URL instead, waiting for `GET /api/v1/flows/{id}` and the canvas to
mount. The id is read AFTER the blank-flow navigation, never before it: the
bootstrap reaches the templates modal through "New Flow", which parks the page
on a placeholder flow Langflow deletes as soon as the modal navigates elsewhere
(#490/#681 from the other side).

Each exit now asserts the editor was actually left. That is the attribution
this flake lacked: a failed save leaves the editor in place, which surfaced
45 s later as a card-click timeout naming neither the step nor the cause.
Verified by forcing the save PATCH to 500 — the failure now lands on the exit.

Quarantine lifted: `test.fixme` removed and `@stable` restored.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a recurrent flake in the auto-save-off @stable flow test by ensuring the spec always re-opens the exact flow it created (by flow id) rather than relying on ambiguous, paginated list-card selection by name.

Changes:

  • Replaces “reopen by flows-list card filtered by New Flow” with “reopen by /flow/<id> and wait for GET /api/v1/flows/<id> + canvas mount”.
  • Adds editorFlowId cross-check and expectLeftEditor assertions so “wrong flow” and “failed exit” failures surface at the correct step.
  • Restores @stable on the spec and updates the spec doc’s validated version and narrative accordingly.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
tests/tests-automations/regression/flow-functionality/auto-save-off.spec.ts Reopens the flow under test by id (URL) with response-based readiness, adds editor-exit assertions, and restores @stable.
docs/flow-functionality/auto-save-off.md Updates last-validated version and documents the id-based reopen + exit assertions rationale for #1336.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Victor-w-Madeira
Victor-w-Madeira merged commit 084e69b into main Aug 6, 2026
8 checks passed
@Victor-w-Madeira
Victor-w-Madeira deleted the fix/issue-1336-auto-save-off-reopen-by-id branch August 6, 2026 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

daily-failure Failure detected by the daily @stable E2E workflow

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Daily #1330] auto-save-off — reopening the just-created flow's card intermittently times out at 45 s (recurrent 2×)

2 participants