You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
test(cli): TestRecommendationCompletenessCommand/savingsplans-database/api-error is flaky in CI #2140
The integration subtest TestRecommendationCompletenessCommand/savingsplans-database/api-error (cmd/recommendation_completeness_test.go, added in #2130) failed once in CI on a docs-only PR branch, then passed on a rerun of semantically identical code.
Passed: run 37625552805 on 82cdc92 (same branch, docs-only delta).
Main is green at the shared base ad57326 (run 37615190817).
A docs-only change cannot affect this test, so the failure indicates nondeterminism in the test or its fixtures (timing, map iteration order, or simulated API-error propagation).
Expected behaviour
The subtest is deterministic: same inputs, same verdict, every run.
Suggested investigation
Run the subtest in a loop with -count=50 -shuffle=on locally to reproduce.
Check for map-order dependence in the synthetic operation counts logged by the test (synthetic operations=map[...]) and for timing assumptions in the api-error path.
Investigation by [claude-cli-impl] on origin/main 817ab4b. I'm releasing the claim with no code change, because the failure does not reproduce and a fix without a root cause would be speculative.
What failed in run 37624743342 (fc23e47, Go 1.26.6, -race, Linux)
The assertion was require.Contains(logs, "fixture denied recommendations"), now at cmd/recommendation_completeness_test.go:78.
The child process got GetSavingsPlansPurchaseRecommendation ... StatusCode: 400 ... deserialization failed, failed to copy error response body, read tcp 127.0.0.1:...: use of closed network connection.
The fixture's 400 was correct and was counted once by the proxy. The client's own socket was closed locally while it read the error body, so the fixture JSON was never parsed.
This is the only occurrence in the 10 most recent failed CI runs.
8, 24 and 60 parallel processes, up to about 6x CPU oversubscription, with -cpu 1,2.
The child process with GOMAXPROCS=1 and 2.
The fixture writing its response slowly, 3ms per write.
The full TestRecommendationCompletenessCommand: 12 processes × 6 runs, about 2,500 subtests.
Ruled out
Map ordering: the SP path is sequential (collection_sp.go:121-146).
Context cancellation: a cancel would surface canceledErr, not the raw net error.
Production CloseIdleConnections: there are no callers. The only one is the child test's cleanup, which runs after Execute.
The fixture closing the connection: that would show EOF or reset, and the 40s deadline is not reached.
Remaining hypotheses (unproven)
A rare net/http persistConn close on a loaded 2-core runner. Candidates are closeConnIfStillIdle, the writeLoop close and the readLoop peek-fail close.
A Go 1.26.6 transport issue. CI was on 1.26.6, and go.mod is now 1.26.9.
A race in the child's http.DefaultTransport swap. This is unlikely, because the SDK uses its own client.
Next step if it recurs: capture the failing run ID and Go version. To instrument it, build with a -overlay copy of persistConn.closeLocked that prints a stack when the connection closes mid-body, and run that on Linux with limited CPU.
I'm adding status/needs-info until a second occurrence gives more data.
Activity
cristim commentedon Oct 16, 2026
Claiming: working on this [claude-cli-impl]
cristim commentedon Oct 16, 2026
Investigation by [claude-cli-impl] on origin/main 817ab4b. I'm releasing the claim with no code change, because the failure does not reproduce and a fix without a root cause would be speculative.
What failed in run 37624743342 (fc23e47, Go 1.26.6,
-race, Linux)require.Contains(logs, "fixture denied recommendations"), now atcmd/recommendation_completeness_test.go:78.GetSavingsPlansPurchaseRecommendation ... StatusCode: 400 ... deserialization failed, failed to copy error response body, read tcp 127.0.0.1:...: use of closed network connection.Reproduction attempts (about 5,000 runs, 0 failures)
-count=100, under-race.-cpu 1,2.TestRecommendationCompletenessCommand: 12 processes × 6 runs, about 2,500 subtests.Ruled out
collection_sp.go:121-146).canceledErr, not the raw net error.CloseIdleConnections: there are no callers. The only one is the child test's cleanup, which runs after Execute.Remaining hypotheses (unproven)
persistConnclose on a loaded 2-core runner. Candidates arecloseConnIfStillIdle, thewriteLoopclose and the readLoop peek-fail close.http.DefaultTransportswap. This is unlikely, because the SDK uses its own client.Next step if it recurs: capture the failing run ID and Go version. To instrument it, build with a
-overlaycopy ofpersistConn.closeLockedthat prints a stack when the connection closes mid-body, and run that on Linux with limited CPU.I'm adding
status/needs-infountil a second occurrence gives more data.