Skip to content

flake: TestProxy_HotReloadRouting (multiple variants, Windows EOF) #1564

Open

Description

@flake-investigator

This issue tracks intermittent Windows EOF failures from routed HTTPS requests in the enterprise/aibridgeproxyd hot-reload test family. The routing decision succeeds, but the loopback proxy-to-aibridged round trip returns no response; goproxy closes the MITM connection and the test client surfaces EOF.

Original occurrence:

CI Run: https://github.com/coder/coder/actions/runs/26933139214
Job: https://github.com/coder/coder/actions/runs/26933139214/job/79456825080
Commit: becc858fa85182ed55a45d1a317bc7e60da8f8bb (author: Ethan)

Failure:

=== FAIL: enterprise/aibridgeproxyd TestProxy_HotReloadRoutingInvalidProviders/RefreshErrorPreservesPreviousSnapshot
    reload_test.go:574:
        Error: Received unexpected error:
        Post "https://alpha.invalid/v1/messages": EOF
        Messages: request to routed host must succeed

Error analysis:

  • The proxy routed request to aibridged returned EOF during the "refresh error preserves previous snapshot" assertion.
  • The test expects the previous router snapshot to continue serving requests after a reload error; the EOF suggests a transient proxy/MITM connection failure.

Root cause classification: flaky test / Windows loopback infrastructure pressure.

Race/Panic/OOM evidence: none found in the original logs.

Assignment analysis:

  • git log --oneline -10 --follow enterprise/aibridgeproxyd/reload_test.go
    • 12520ee964 "feat: add ai provider status and reload freshness metrics" (Danny Kopping)
    • a9f5ed7644 "fix: re-validate provider per request and classify reloads" (Danny Kopping)
    • 79e007cf30 "feat: hot-reload aibridged and aibridgeproxyd providers on DB changes" (Danny Kopping; introduced this test file and CRUD test)

Assigned to Danny based on test/component ownership, not the failing commit author.

Reproduction:

  • go test ./enterprise/aibridgeproxyd -run 'TestProxy_HotReloadRouting' -count=100
  • The original occurrence could not be reproduced on Linux after 5,000+ iterations; the observed failures are on Windows under full-suite loopback connection churn.

Activity

  1. linear-code commented on Jun 4, 2026

    @linear-code
  2. dannykopping commented on Jun 19, 2026

    @dannykopping
    Collaborator

    I couldn't see anything obviously wrong here, and I got Opus 4.8 to look closer:


    Root cause: transient network blip on the Windows CI runner, not a product bug

    The failure is on the test-go-pg (windows-2022) runner. The CI slog output shows both routed requests in the subtest:

    • Request 1: routing MITM request to aibridged ... provider=alpha → received response from aibridged status=200 ✅
    • Request 2: routing MITM request to aibridged ... provider=alpha → no response line → Post "https://alpha.invalid/v1/messages": EOF ❌

    Key takeaways

    1. The routing logic worked correctly. Request 2 was re-validated against the live router, matched provider=alpha, and was forwarded to aibridged. It did not hit the pass-through branch, so the "refresh error preserves snapshot" behavior and the per-request re-validation (commits a9f5ed7644 / 12520ee964) are fine.

    2. The EOF came from the proxy→aibridged hop. The missing received response from aibridged line means proxy.Tr.RoundTrip() to the loopback aibridged backend returned an error. goproxy handles an upstream round-trip error by silently closing the client's MITM TLS connection with no response, so the client surfaces a bare EOF.

    3. Not a stale-connection reuse race. I instrumented the backend: every request arrives on a fresh source port with Connection: close (the test client's DisableKeepAlives propagates through the MITM), so each request opens and tears down fresh TCP connections. The two requests are structurally identical; one just hiccupped.

    4. Environmental trigger. ~24k tests churning fresh loopback connections on Windows (ephemeral-port / TIME_WAIT pressure) makes a one-off fresh-connect/round-trip failure plausible. Could not reproduce on Linux (5000+ iterations under -race, low GOMAXPROCS, high parallelism = all green).

    Why the test fails on a blip

    expectRoutedTo treats any request error as fatal (require.NoError(..., "request to routed host must succeed")). A single transient TCP/TLS error doesn't disprove "this host is routed to aibridged."

  3. changed the title [-]flake: TestProxy_HotReloadRoutingInvalidProviders/RefreshErrorPreservesPreviousSnapshot[/-] [+]flake: TestProxy_HotReloadRouting (multiple variants, Windows EOF)[/+] on Aug 4, 2026
  4. flake-investigator commented on Aug 4, 2026

    @flake-investigator
    Author

    New occurrence of the same Windows routed-request EOF failure mode.

    Key evidence:

    === FAIL: enterprise/aibridgeproxyd TestProxy_HotReloadRoutingCRUD (0.16s)
    ...
    aibridgeproxyd router reloaded  provider_count=1 ... mitm_hosts=[alpha.invalid:443]
    request CONNECT authenticated ... host=alpha.invalid:443  provider=alpha
    routing MITM request to AI Gateway ... host=alpha.invalid ... provider=alpha  gateway_target_url=http://127.0.0.1:64055/alpha/v1/messages
    reload_test.go:407:
        Error: Received unexpected error:
            Post "https://alpha.invalid/v1/messages": EOF
        Messages: request to routed host must succeed
    

    This ties directly to the original occurrence: the router successfully reloaded and selected alpha, CONNECT authentication succeeded, and the request entered the MITM-to-gateway path, but no backend response was logged before the client received EOF. That matches the previously analyzed transient Windows loopback proxy-to-aibridged round-trip failure rather than incorrect hot-reload routing.

    Root cause classification: flaky test / Windows loopback infrastructure pressure. The full 2,711-line job log contains one test failure and no process crash. Race detection was disabled for this job; there are no WARNING: DATA RACE / race detected indicators. There are also no panic:, runtime fatal, OOM, signal: killed, disk, file-descriptor, or resource-exhaustion indicators.

    Assignment trace:

    • git blame -L 391,473 enterprise/aibridgeproxyd/reload_test.go points the CRUD test/harness ownership to the hot-reload work introduced in 79e007cf30 by Danny Kopping.
    • git log --oneline -10 --follow enterprise/aibridgeproxyd/reload_test.go shows the latest meaningful test/component changes in 12520ee964, a9f5ed7644, and 79e007cf30, all by Danny.
    • The failing commit only changes CI module-download retry behavior and is not used for assignment.

    Suggested reproduction/stress command on Windows:

    go test ./enterprise/aibridgeproxyd -run TestProxy_HotReloadRoutingCRUD -count=100
    
  5. dannykopping commented on Aug 4, 2026

    @dannykopping
    Collaborator

    Same issue, closing

  6. removed their assignment
    on Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions