Skip to content

fix(llm): use Windows WSA errnos instead of string matching#953

Merged
cpcloud merged 3 commits intomicasa-dev:mainfrom
cpcloud:fix-windows-wsa-errnos
Apr 18, 2026
Merged

fix(llm): use Windows WSA errnos instead of string matching#953
cpcloud merged 3 commits intomicasa-dev:mainfrom
cpcloud:fix-windows-wsa-errnos

Conversation

@cpcloud
Copy link
Copy Markdown
Collaborator

@cpcloud cpcloud commented Apr 18, 2026

Summary

  • Follow-up to refactor: eliminate fragile error-string matching #951. The Windows CI failure resolved there with a string-matching fallback has a deeper, fully typed fix.
  • syscall.ECONNREFUSED on Windows is defined as `APPLICATION_ERROR | iota` (an invented value, not the real WSA error code), so `errors.Is(err, syscall.ECONNREFUSED)` always returns false on Windows for real network errors. Same for `ENETUNREACH` and `EHOSTUNREACH`.
  • Split `connectionErrnos` across build-tagged files: POSIX uses the standard `syscall.*` constants; Windows uses `golang.org/x/sys/windows.WSAECONNREFUSED` / `WSAENETUNREACH` / `WSAEHOSTUNREACH` (already a direct dep, exposed as `syscall.Errno` so `errors.Is` works).
  • `isNetworkError` collapses to a simple loop over the platform-specific list; the substring fallback comes out. Zero string matching on either platform.
  • `AGENTS.md`: codify "no `err.Error()` substring classification" with the Windows errno caveat documented inline so the next agent doesn't fall into the same trap.

cpcloud added 2 commits April 18, 2026 07:05
The previous fix restored substring matching for the Windows CI
failure, but the real cause is more fundamental: syscall.ECONNREFUSED
on Windows is an APPLICATION_ERROR-prefixed invented constant
(1<<29 + iota), NOT the actual WSA error code (10061) that net/http
returns. errors.Is can never match it on Windows because the values
are different integers.

Split the errno sentinel list across build-tagged files: POSIX uses
the standard syscall constants; Windows uses windows.WSAECONNREFUSED,
WSAENETUNREACH, and WSAEHOSTUNREACH from golang.org/x/sys/windows
(already a direct dep, exposed as syscall.Errno). isNetworkError
becomes a simple loop that calls errors.Is on the right values for
the current platform. Zero string matching on either platform.
…rrno gotcha

Codify the lesson from the connectex CI failure. syscall.ECONNREFUSED
on Windows is APPLICATION_ERROR + iota, NOT the WSA error code that
net/http surfaces, so errors.Is against the standard syscall.Errno
sentinels always returns false. The fix is build-tagged sentinel lists
that use golang.org/x/sys/windows.WSA* on Windows; see
internal/llm/network_errors_{windows,other}.go for the pattern.
@cpcloud cpcloud added documentation Improvements or additions to documentation refactor Code restructuring without behavior change llm LLM and chat features labels Apr 18, 2026
The previous commit gated isNetworkError on platform-specific
connectionErrnos but left the tests wrapping syscall.ECONNREFUSED
directly. On Windows that's an APPLICATION_ERROR-prefixed invented
constant, not the WSA value the production check uses, so the tests
failed on windows-11-arm CI. Reach into connectionErrnos[0] for the
representative connection-refused sentinel; it resolves to
syscall.ECONNREFUSED on POSIX and windows.WSAECONNREFUSED on Windows.
@cpcloud cpcloud merged commit d14769a into micasa-dev:main Apr 18, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation llm LLM and chat features refactor Code restructuring without behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant