Skip to content

Live VCS status/diff test on Windows: 'connection forcibly closed by the remote host' #472

Open

Description

@Blind-Striker

VcsClientLiveTests.GetStatusAsync_And_GetDiffAsync_Should_Report_A_Modified_Tracked_File failed once on the Windows CI leg (net10.0). Its pinned live server dropped the connection mid-request.

Observation

  • Run: CI run 39077427835, job Build & Test (Windows), on PR fix(generator): a curated hoisted member is called optional only when it is #468 at head 80ddef3e (2026-10-17 23:12 UTC).

  • Test: tests/OpenCode.Sdk.Tests/Vcs/VcsClientLiveTests.cs:73, on OpenCode.Sdk.Tests.dll (net10.0|x64); 10.5 s to failure.

  • Error:

    [Test Failure] OpenCodeTransportException: The opencode server could not be reached.
     ---> System.Net.Http.HttpRequestException: An error occurred while sending the request.
     ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..
    
  • Unrelated to the PR: PR fix(generator): a curated hoisted member is called optional only when it is #468 is tools-only, and its generated output is byte-identical (generate --verify current). On the same run:

    • Linux, macOS, lint and CodeQL are green;
    • the Windows leg's other test assemblies passed, including Tools.Tests at 2089/0;
    • this was the only failure in OpenCode.Sdk.Tests.
  • Rerun: I reran the failed job after filing this record. The rerun's result will be added here.

Owner and suspected area

Activity

  1. Blind-Striker commented on Oct 17, 2026

    @Blind-Striker
    CollaboratorAuthor

    Rerun result: the rerun of the failed Windows job in run 39077427835 (same head 80ddef3e, no code change) passed, VcsClientLiveTests included. So this is an intermittent failure, not a deterministic one on that head.

  2. added this to the 1.0 milestone on Oct 18, 2026
  3. Blind-Striker commented on Oct 18, 2026

    @Blind-Striker
    CollaboratorAuthor

    Targeted probe: not reproduced.

    Setup: a client against the pinned server (2.0.32) on Windows. Each attempt makes one request, waits a delay d around the server's idle close, and then reuses the connection. There were six delays from T−200 ms to T+50 ms, 10 attempts each, on net10.0 and on net472. A second client with a shorter idle timeout served as the control.

    • The server's idle close: T ≈ 6.0 s (median 6017 ms over 3 samples). The server advertises Connection: keep-alive and Keep-Alive: timeout=5.
    • Result: 240 of 240 attempts succeeded, controls included, with 0 resets. The offsets are 10 ms apart and the close was measured with 25 ms polling, so a narrower close-while-sending race is not ruled out.

    Gap found. The SDK sets no idle timeout. The modern transport sets only PooledConnectionLifetime (120 s), so the default 60 s idle applies; net472 sets no ServicePoint.MaxIdleTime. A pooled connection can therefore outlive the server's 5–6 s idle close.

    • A clean close is caught by the handler's reuse check, which is why the probe stays green.
    • A reset that lands while a request is being sent surfaces as a non-retryable HttpRequestException, which matches this failure.

    Upstream's first-party client (undici under Node) honours the Keep-Alive hint minus 2 s, so it does not reuse a connection idle for more than about 3 s.

    Next: an idle timeout below the server's hint, as parity hardening, is with the maintainer. It is not claimed as a proven fix for this failure. This issue stays open under #506 until that decision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions