Skip to content

Flaky: group rm "should delete group with workloads" times out waiting for readiness #6040

Description

@JAORMX

Summary

Group RM E2E Tests > thv group rm command > [It] should delete group with workloads (test/e2e/group_rm_test.go:124) fails intermittently in the E2E Tests Core (core) shard, on commits that have nothing to do with groups or workloads.

Summarizing 1 Failure:
  [FAIL] Group RM E2E Tests  thv group rm command  [It] should delete group with workloads  [core, groups, e2e]
  /home/runner/work/toolhive/toolhive/test/e2e/group_rm_test.go:124

Ran 60 of 507 Specs in 506.503 seconds
FAIL! -- 59 Passed | 1 Failed | 0 Pending | 447 Skipped

Where it fails, and why that matters

Line 124 is the readiness assertion inside the wait loop, not one of the group rm assertions:

// Verify all workloads are running
for _, workloadName := range []string{groupWorkload1, groupWorkload2, nonGroupWorkload1, nonGroupWorkload2} {
    err := e2e.WaitForMCPServer(config, workloadName, e2e.ServerReadyTimeout())
    Expect(err).ToNot(HaveOccurred())   // <-- line 124
}

So the spec is not finding a bug in thv group rm — it is failing to get four containerised workloads ready in time. This is the heaviest setup of any spec in the file (the neighbouring specs start two), and it runs on a CI runner concurrently hosting other e2e shards. That makes it the natural first casualty of any transient slowness in image pull, container start, or proxy readiness.

Notably the four workloads are started sequentially and each waited on separately, but the failure surfaces as a bare "workload didn't become ready" without saying which of the four, because the loop reuses one assertion with no message. That alone makes triage harder than it needs to be.

Evidence it is pre-existing, not caused by any PR

The core shard has failed on main on unrelated commits, and passed on others:

Run Commit E2E Tests Core (core)
30268388184 f1dae946
30264963508 d3907301
30264573849 96f25d05
8a860d9b
e837d694

It most recently blocked #6031, whose diff touches only pkg/transport/session and pkg/transport/proxy/transparent — nothing reachable from thv group rm.

Secondary hazard worth fixing at the same time

Workload names in this file are built from GinkgoRandomSeed():

groupWorkload1 := fmt.Sprintf("group-rm-group-workload-1-%d", GinkgoRandomSeed())

GinkgoRandomSeed() is the suite's seed — constant for the whole run, not per-spec. So these names are stable across every spec in a run and, more importantly, are not unique across runs. A leftover container from a previous run that used the same seed collides by name. Every other e2e suite in this repo uses e2e.GenerateUniqueServerName for exactly this reason; group_rm_test.go has zero uses of it. That is a latent second flake source even if the timeout is addressed.

Suggested directions

Not prescribing, since the right call depends on whether the timeout is genuinely too tight or the spec is simply doing too much:

  • Name the failing workload. Add the workload name to the assertion message so the next failure says which of the four timed out — cheap, and turns this from a guess into a fact.
  • Reduce the setup. The spec's actual subject is "group workloads survive group rm, non-group workloads keep running". It may not need four workloads to establish that; two (one in-group, one out) might suffice.
  • Switch to e2e.GenerateUniqueServerName throughout the file, matching the rest of the suite.
  • Check whether ServerReadyTimeout() is realistic for four sequential container starts on a shared runner, versus the two the neighbouring specs use.

Context

This is the fourth distinct pre-existing flake to surface in our PRs today, alongside #6026 (optimizer search-quality spec), #6034 (getFreePort bind-close-rebind race), and a transient curl: (35) fetching the kind binary in helm/kind-action. Filing this one because it has a clear signature and a reproducible history on main, and because it has already sent one investigation down the wrong path — a red core shard on an unrelated PR reads as that PR's fault until someone opens the log.

Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageIssue needs initial triage by a maintainer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions