Skip to content

fix: WSL2 Ollama networking and provider discovery diagnostics#55435

Merged
BradGroux merged 4 commits intoopenclaw:mainfrom
kinfey:pr/wsl2-ollama-diagnostics
Mar 27, 2026
Merged

fix: WSL2 Ollama networking and provider discovery diagnostics#55435
BradGroux merged 4 commits intoopenclaw:mainfrom
kinfey:pr/wsl2-ollama-diagnostics

Conversation

@kinfey
Copy link
Copy Markdown
Contributor

@kinfey kinfey commented Mar 27, 2026

  • Fix Ollama stream handling for WSL2 environments
  • Update undici global dispatcher for WSL2 networking compatibility
  • Adjust provider discovery configuration
  • Add WSL2 networking tests

fixed #54498

- Fix Ollama stream handling for WSL2 environments
- Update undici global dispatcher for WSL2 networking compatibility
- Adjust provider discovery configuration
- Add WSL2 networking tests
@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: XS labels Mar 27, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 27, 2026

Greptile Summary

This PR fixes WSL2 networking issues with Ollama by disabling undici's autoSelectFamily option when running inside WSL2, forcing IPv4 connections and preventing TypeError: fetch failed errors caused by unstable IPv6 paths to Windows-host services. It also improves error diagnostics across the Ollama stack by surfacing the nested error.cause.message in both stream error output and provider discovery logging.\n\n- undici-global-dispatcher.ts: resolveAutoSelectFamily() now calls isWSL2Sync() and returns false (override to IPv4) when the system default would otherwise enable autoSelectFamily on a WSL2 host.\n- ollama-stream.ts: Catch block appends err.cause.message to the user-visible error string and logs it via log.warn, helping diagnose undici-wrapped network failures.\n- models-config.providers.discovery.ts: Discovery failure log similarly appends the nested cause message for improved diagnostics.\n- undici-global-dispatcher.test.ts: Adds a ../wsl.js mock and a new test confirming that autoSelectFamily is set to false under WSL2. The beforeEach does not reset the isWSL2Sync mock implementation after vi.clearAllMocks(), which makes the test suite order-dependent — this should be addressed with an explicit vi.mocked(isWSL2Sync).mockReturnValue(false) in beforeEach.

Confidence Score: 4/5

Safe to merge after fixing the isWSL2Sync mock reset in beforeEach to prevent order-dependent test failures.

The core production changes are sound: the WSL2 detection logic is well-established, the IPv4 override is narrowly scoped and idempotency-safe, and the diagnostics improvements are straightforward. The one actionable issue is a test-reliability gap — vi.clearAllMocks() does not reset mockReturnValue implementations, so the new WSL2 test leaves isWSL2Sync returning true for any subsequently added tests. This is a one-line fix in beforeEach and doesn't affect current test outcomes (the WSL2 test is last in its block), but it warrants resolution before merge to avoid silent future regressions.

src/infra/net/undici-global-dispatcher.test.ts — needs explicit isWSL2Sync mock reset in beforeEach.

Important Files Changed

Filename Overview
src/infra/net/undici-global-dispatcher.ts Introduces WSL2-aware resolveAutoSelectFamily: when net.getDefaultAutoSelectFamily() returns true and isWSL2Sync() confirms a WSL2 environment, the function overrides the result to false to force IPv4.
src/infra/net/undici-global-dispatcher.test.ts Adds mock for ../wsl.js and a new test verifying WSL2 disables autoSelectFamily. The beforeEach doesn't reset the isWSL2Sync mock implementation, making test order slightly fragile if new tests are added after the WSL2 case.
src/agents/ollama-stream.ts Error handling now appends err.cause.message to the user-facing error message and logs it separately, improving diagnostics for undici's wrapped TypeError: fetch failed errors.
src/agents/models-config.providers.discovery.ts Extends Ollama discovery failure log to include the nested error.cause.message when present, mirroring the same diagnostic improvement made in ollama-stream.ts.

Comments Outside Diff (1)

  1. src/infra/net/undici-global-dispatcher.test.ts, line 78-91 (link)

    P1 Missing isWSL2Sync mock reset in beforeEach

    vi.clearAllMocks() only resets call history (mock.calls, mock.results), not implementations set by mockReturnValue. The WSL2 test at line 160 sets vi.mocked(isWSL2Sync).mockReturnValue(true), and because clearAllMocks doesn't reset that implementation, any test added after the WSL2 case will unexpectedly see isWSL2Sync returning true. This would silently break, e.g., the "replaces default Agent dispatcher" assertion that expects autoSelectFamily: true.

    Adding an explicit reset in beforeEach keeps the suite order-independent:

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/infra/net/undici-global-dispatcher.test.ts
    Line: 78-91
    
    Comment:
    **Missing `isWSL2Sync` mock reset in `beforeEach`**
    
    `vi.clearAllMocks()` only resets call history (`mock.calls`, `mock.results`), not implementations set by `mockReturnValue`. The WSL2 test at line 160 sets `vi.mocked(isWSL2Sync).mockReturnValue(true)`, and because `clearAllMocks` doesn't reset that implementation, any test added after the WSL2 case will unexpectedly see `isWSL2Sync` returning `true`. This would silently break, e.g., the "replaces default Agent dispatcher" assertion that expects `autoSelectFamily: true`.
    
    Adding an explicit reset in `beforeEach` keeps the suite order-independent:
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/infra/net/undici-global-dispatcher.test.ts
Line: 78-91

Comment:
**Missing `isWSL2Sync` mock reset in `beforeEach`**

`vi.clearAllMocks()` only resets call history (`mock.calls`, `mock.results`), not implementations set by `mockReturnValue`. The WSL2 test at line 160 sets `vi.mocked(isWSL2Sync).mockReturnValue(true)`, and because `clearAllMocks` doesn't reset that implementation, any test added after the WSL2 case will unexpectedly see `isWSL2Sync` returning `true`. This would silently break, e.g., the "replaces default Agent dispatcher" assertion that expects `autoSelectFamily: true`.

Adding an explicit reset in `beforeEach` keeps the suite order-independent:

```suggestion
  beforeEach(async () => {
    vi.resetModules();
    ({
      DEFAULT_UNDICI_STREAM_TIMEOUT_MS,
      ensureGlobalUndiciEnvProxyDispatcher,
      ensureGlobalUndiciStreamTimeouts,
      resetGlobalUndiciStreamTimeoutsForTests,
    } = await import("./undici-global-dispatcher.js"));
    vi.clearAllMocks();
    resetGlobalUndiciStreamTimeoutsForTests();
    setCurrentDispatcher(new Agent());
    getDefaultAutoSelectFamily.mockReturnValue(undefined);
    vi.mocked(hasEnvHttpProxyConfigured).mockReturnValue(false);
    vi.mocked(isWSL2Sync).mockReturnValue(false);
  });
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: WSL2 Ollama networking and provider..." | Re-trigger Greptile

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 98666899a6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5c21c88fd8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5245d00f51

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@BradGroux
Copy link
Copy Markdown
Contributor

Review: WSL2 Ollama Diagnostics

Verdict: Approve -- clean, focused, and solves a real pain point for WSL2 users.

Reviewed the full diff across all 4 files. This is exactly the right scope (compared to the earlier #55187 which bundled unrelated changes). Notes below from two independent review passes.

What works well

  • Targeted fix: autoSelectFamily: false on WSL2 sidesteps the IPv6 routing mess that breaks Ollama connections. Uses the existing isWSL2Sync() helper, no new dependencies.
  • Better error messages: Unwrapping error.cause from undici's generic TypeError: fetch failed surfaces the actual network error (ECONNREFUSED, EHOSTUNREACH, etc.) in both the Ollama stream path and provider autodiscovery. Users will actually know what went wrong now.
  • Test coverage: New test case validates the WSL2 dispatcher override behavior.

Suggestions (non-blocking)

  1. Comment accuracy on autoSelectFamily: The inline comment says disabling autoSelectFamily "forces IPv4," but technically it just skips the Happy Eyeballs algorithm and uses whichever address DNS returns first. In practice this works because Ollama binds to 127.0.0.1, but the comment is slightly misleading. Consider rewording to something like "disables dual-stack auto-selection to avoid WSL2 IPv6 routing issues."

  2. Test mock cleanup: The isWSL2Sync mock is set to return true in the WSL2 test block, but vi.clearAllMocks() in beforeEach clears call counts without resetting mockReturnValue implementations. Consider adding vi.restoreAllMocks() or scoping the mock with vi.spyOn to prevent leaking into subsequent tests.

  3. Error-cause unwrapping is untested: The .cause surfacing in ollama-stream.ts and models-config.providers.discovery.ts has no corresponding test cases. A quick test that throws a TypeError wrapping an ECONNREFUSED cause and asserts the unwrapped message appears in the error output would lock this behavior in.

  4. Pre-existing: isWSL2Sync() does uncached sync I/O: Reads /proc/version synchronously on every call. This is not introduced by this PR and only runs once during dispatcher init, so not blocking. Worth noting for a future follow-up if the function gets called in hotter paths (it is also used in pi-embedded-runner/run/attempt.ts).

Summary

All four items are minor hardening suggestions. The core fix is correct, minimal, and solves the reported issue in #54498. Good to merge.

Copy link
Copy Markdown
Contributor

@BradGroux BradGroux left a comment

Choose a reason for hiding this comment

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

Approved. Clean, focused fix for WSL2 Ollama connectivity.

@BradGroux BradGroux merged commit c959ac3 into openclaw:main Mar 27, 2026
34 of 36 checks passed
pxnt pushed a commit to pxnt/openclaw that referenced this pull request Mar 27, 2026
…law#55435)

- Fix Ollama stream handling for WSL2 environments
- Update undici global dispatcher for WSL2 networking compatibility
- Adjust provider discovery configuration
- Add WSL2 networking tests
godlin-gh pushed a commit to YouMindInc/openclaw that referenced this pull request Mar 27, 2026
…law#55435)

- Fix Ollama stream handling for WSL2 environments
- Update undici global dispatcher for WSL2 networking compatibility
- Adjust provider discovery configuration
- Add WSL2 networking tests
w-sss pushed a commit to w-sss/openclaw that referenced this pull request Mar 28, 2026
…law#55435)

- Fix Ollama stream handling for WSL2 environments
- Update undici global dispatcher for WSL2 networking compatibility
- Adjust provider discovery configuration
- Add WSL2 networking tests
alexcode-cc pushed a commit to alexcode-cc/clawdbot that referenced this pull request Mar 30, 2026
…law#55435)

- Fix Ollama stream handling for WSL2 environments
- Update undici global dispatcher for WSL2 networking compatibility
- Adjust provider discovery configuration
- Add WSL2 networking tests
livingghost pushed a commit to livingghost/openclaw that referenced this pull request Mar 31, 2026
…law#55435)

- Fix Ollama stream handling for WSL2 environments
- Update undici global dispatcher for WSL2 networking compatibility
- Adjust provider discovery configuration
- Add WSL2 networking tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants