fix: Windows LSP URIs using backslashes (Biome initialization failure)
Summary
On Windows, the LSP client is currently sending URIs built from Windows paths with backslashes (\). This results in invalid file:// URIs and causes strict LSP servers like Biome to fail during initialize with a URI parsing error (e.g. “unexpected character at index 9”).
LSP requires URIs conforming to RFC 3986, which uses / as the path separator even on Windows (e.g. file:///c:/project/file.ts).
Evidence
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"typescript":{
"disabled": true
},
"biome": {
"command": [
"bunx",
"@biomejs/biome@latest",
"lsp-proxy",
"--stdio"
],
"extensions": [
".js",
".mjs",
".cjs",
".jsx",
".ts",
".mts",
".cts",
".tsx",
".d.ts",
".d.mts",
".d.cts",
".json",
".jsonc",
".css",
".html",
".htm",
".graphql",
".gql",
".vue",
".svelte",
".astro"
]
}
}
}
Example log when opening a file on Windows:
INFO 2025-12-10T09:55:29 +17ms service=lsp file=.\web\provaH.html touching file
INFO 2025-12-10T09:55:29 +143ms service=lsp serverID=biome spawned lsp server
INFO 2025-12-10T09:55:29 +1ms service=lsp.client serverID=biome starting client
INFO 2025-12-10T09:55:29 +3ms service=lsp.client serverID=biome sending initialize
ERROR 2025-12-10T09:55:30 +1113ms service=lsp.client serverID=biome error=unexpected character at index 9 initialize error
ERROR 2025-12-10T09:55:30 +0ms service=lsp error=LSPInitializeError Caused by: unexpected character at index 9 Failed to initialize LSP client biome
INFO 2025-12-10T09:55:30 +1ms service=default directory=C:\Users\alopez\Desktop\repos\infordisa-portal-nat disposing instance
This matches what you’d expect if the LSP server receives a URI like:
file:///C:\Users\...
instead of:
file:///c:/Users/...
Current Fix
I’ve implemented a change so that, when building URIs from filesystem paths, we now use:
import { pathToFileURL } from "url";
const uri = pathToFileURL(item).href;
This is done to let Node handle the file:// URI normalization (including converting backslashes to forward slashes and properly encoding the path).
On Windows, this fixes the issue in my tests: Biome now initializes correctly and works as expected.
Fix Evidence
INFO 2025-12-10T11:07:15 +1ms service=lsp.client serverID=biome starting client
INFO 2025-12-10T11:07:15 +4ms service=lsp.client serverID=biome sending initialize
INFO 2025-12-10T11:07:15 +9ms service=vcs branch=fix/windows-uri-fix-lsp initialized
INFO 2025-12-10T11:07:15 +0ms service=bus type=file.watcher.updated subscribing
INFO 2025-12-10T11:07:16 +1293ms service=lsp.client serverID=biome initialized
INFO 2025-12-10T11:07:16 +0ms service=bus type=lsp.updated publishing
INFO 2025-12-10T11:07:16 +1ms service=lsp.client serverID=biome path=C:\Users\alopez\Desktop\repos\infordisa-portal-nat\web\provaH.html waiting for diagnostics
INFO 2025-12-10T11:07:16 +0ms service=bus type=lsp.client.diagnostics subscribing
INFO 2025-12-10T11:07:16 +2ms service=lsp.client serverID=biome path=C:\Users\alopez\Desktop\repos\infordisa-portal-nat\web\provaH.html textDocument/didOpen
INFO 2025-12-10T11:07:19 +3007ms service=bus type=lsp.client.diagnostics unsubscribing
{}
INFO 2025-12-10T11:07:19 +1ms service=default directory=C:\Users\alopez\Desktop\repos\opencode\packages\opencode disposing instance
INFO 2025-12-10T11:07:19 +0ms service=state key=C:\Users\alopez\Desktop\repos\opencode\packages\opencode waiting for state disposal to complete
INFO 2025-12-10T11:07:19 +2ms service=lsp.client serverID=biome shutting down
INFO 2025-12-10T11:07:19 +2ms service=lsp.client serverID=biome shutdown
Disclaimer / Request for Review
I’m not very experienced with URI edge cases (UNC paths, non-ASCII, already-encoded paths, etc.), so while pathToFileURL(item).href looks like the correct and simplest solution, I’m not 100% sure there are no side effects on other platforms or setups.
Feel free to offer improvements, comments, or whatever. And do some extra testing before merging this.
/review
lgtm
If anything else is needed tell me