Skip to content

Conversation

@pschiel
Copy link
Contributor

@pschiel pschiel commented Feb 4, 2026

Fixes #107

In reference to anomalyco/opencode#6763

Summary

This fix solves a whole series of bugs, resulting from filepath issues with backslashes occuring on Windows.

Solution: normalize all internal paths to forward slashes using centralized Filesystem wrappers

Why this works: all win32 shells work with forward slash paths, this is de-facto industry standard (git, vscode, cmake, ... all use this pattern)

Observed issues

  • git rev-parse --show-toplevel returns E:/x/y forward slash format → worktree/directory mismatch
  • path.resolve(), path.relative(), realpathSync.native(), realpath (bash) break with git bash paths (various issues)
  • /d/x within C drive (/c/) results in things like C:\d\x
  • relative paths not working like expected using cross-drive
  • contains logic not working → issues with permission system and external_directory
  • /tmp inside git bash is something else outside of it
  • tools break using backslash paths (some backslashes get "eaten")
  • escaping hell for agents → requires double/quadruple escaping
  • observed in all win32 native shells (git bash, cmd, powershell/pwsh)
  • few issues in app/desktop (wrong filepath splits/usage)
  • bun hard crashing with segfault when spawn() is used with non-existing directory

Tested with fix

  • local test suite succeeds now with 100% (bun test in packages/opencode)
  • all possible path variants (C:\a\b, C:/a/b, /c/a/b, /cygdrive/c/a/b) are normalized into C:/a/b format
  • full functionality of all tools (ENOENT errors gone, permissions, relative paths, external directory, LSP)
  • worktree/sandbox handling correct
  • tested TUI and desktop
  • bun spawns via bash/pty not segfaulting

How to reproduce/test

  • test suite
  • running prompts with various problematic/mixed filepaths (see attached md example)

Notes

A few more places would require normalization - but they're unused/dead code (should be removed)
Desktop likely having more issues, especially bun.spawn() usage

@marius-kilocode
Copy link
Collaborator

@pschiel Can you confirm this was tested, how you tested it and how I can reproduce?

@pschiel
Copy link
Contributor Author

pschiel commented Feb 4, 2026

@pschiel Can you confirm this was tested, how you tested it and how I can reproduce?

I fixed only issues that were not working, I reproduced all of the errors.

test suite (bun test in packages/opencode) in git bash, cmd and powershell:

your current dev branch:
Screenshot 2026-02-04 021417

with patch:
Screenshot 2026-02-04 025437

other than these, just plenty of usage since ~2 months. backslashes are the biggest problem, relative paths and cross-drive paths. i had a testing command that checked some of these (requires some structure/files setup).

when working in a windows env, it's inevitable that mixed paths come from anywhere, all of them should work:

test-windows-posix-paths.md

@pschiel
Copy link
Contributor Author

pschiel commented Feb 4, 2026

if you require more info / steps to reproduce for a certain tool or so, let me know.

some others were
"run bash tool ls -l with cwd /foo" -> bun segfault (if dir not found, happens regularly)
"write invalid TS file to D:/bla.ts" (cross-drive) -> LSP shows no diagnostics (silent error)
external directory permissions ("accept all") are not stored

issue always same - string matches, contains() checks etc can only work if paths are internally normalized

@pschiel
Copy link
Contributor Author

pschiel commented Feb 4, 2026

you might want to look packages\app\src\custom-elements.d.ts again.

this is a symlink in the repo, which doesn't work in windows, hence the change into a regular file with export. (I noticed a check failing due to this file in your CI)

@marius-kilocode
Copy link
Collaborator

Interesting that the windows runner tests are failing but passing locally for you

@pschiel
Copy link
Contributor Author

pschiel commented Feb 4, 2026

Interesting that the windows runner tests are failing but passing locally for you

these are just e2e tests which do a few clicks and that's it - I don't think the unit+integration tests run in a win32 runner.

@pschiel
Copy link
Contributor Author

pschiel commented Feb 4, 2026

Since last opencode merge, llm.test.ts fails due to BunProc install on Windows. Install takes much longer on Windows, and is not needed for the tests -> Solution: mock BunProc and Plugin 669fbf1

Model picker tests require KILO_API_KEY and KILO_ORG_ID to connect
providers. In fork PR CI where secrets are unavailable, these tests
were failing. Now they skip gracefully when credentials are missing.
@pschiel
Copy link
Contributor Author

pschiel commented Feb 5, 2026

e963daa fixes the cause of the test (linux) fails:

KILO_API_KEY and KILO_ORG_ID are not set in the branch pipeline, but required for tests:

-> no providers connect -> model list is empty -> model picker has no list items -> 4 model picker tests fail

added a check for these vars and skipping the 4 tests so the pipeline is green - if you fix the credentials issue they should run

@pschiel
Copy link
Contributor Author

pschiel commented Feb 5, 2026

the other issue was that the two custom-elements.d.ts files still had type 120000 in git (symlink) but need to be 100644 (regular files)

reason for changing was: symlinks don't work reliably on windows, and vite will fail reading them. changing into regular files with an export works

@pschiel
Copy link
Contributor Author

pschiel commented Feb 5, 2026

all unit/integration tests pass again

 1011 pass
 1 skip
 0 fail

@pschiel
Copy link
Contributor Author

pschiel commented Feb 5, 2026

General Rebase/Conflict info

entire patch is 1 rule "normalize paths on win32 systems via Filesystem wrapper, where otherwise things will break"

  • use Filesystem.normalize() around paths that are stored internally, used for matching, or passed to tools
  • use Filesystem.join() instead if path.join() ONLY when segments are absolute paths and should be converted, otherwise use Filesystem.normalize(path.join(...))
  • use Filesystem.relative() instead of path.relative()
  • use Filesystem.resolve() instead of path.resolve()
  • use Filesystem.dirname() instead of path.dirname()
  • use Filesystem.realpath() instead of fs.realpath() or fs.realpathSync

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows path issues

2 participants