Skip to content

Fix empty diagnostics on Windows from file URI drive-letter mismatch - #17

Open
bskim wants to merge 2 commits into
code-yeongyu:mainfrom
bskim:fix/windows-diagnostics-uri-normalization
Open

Fix empty diagnostics on Windows from file URI drive-letter mismatch#17
bskim wants to merge 2 commits into
code-yeongyu:mainfrom
bskim:fix/windows-diagnostics-uri-normalization

Conversation

@bskim

@bskim bskim commented Jun 25, 2026

Copy link
Copy Markdown

Problem

On Windows, the diagnostics tool always returns no results, even when the
language server reports real errors. This affects servers that do not implement
pull diagnostics (textDocument/diagnostic) and rely on the publishDiagnostics
push path, such as typescript-language-server.

Root cause

The diagnostics store is keyed by file URI, but the write and read paths produce
different URIs for the same file on Windows:

  • publishDiagnostics arrives with a lowercased, percent-encoded drive:
    file:///c%3A/workspace/src/index.ts
  • the lookup uses pathToFileURL(absPath).href, which yields an uppercase,
    unencoded drive: file:///C:/workspace/src/index.ts

diagnosticsStore.get(uri) therefore misses and returns an empty array. The two
forms do not even match case-insensitively because of the %3A vs :
difference. POSIX is unaffected since file URIs there have no drive prefix.

Captured from typescript-language-server on Windows:

didOpen : file:///C:/workspace/proj/src/file.ts
publish : file:///c%3A/workspace/proj/src/file.ts

symbols, goto_definition, and find_references are unaffected because they
use direct request/response rather than the push store.

Fix

Add normalizeDiagnosticUri and apply it on both the store write and read. It
only reconciles the Windows drive prefix (lowercases the drive letter, decodes
the %3A colon) and returns POSIX URIs untouched, so case-sensitive paths are
never collapsed. Guarded by process.platform === "win32".

Also isolates two createSpawnCommand tests that implicitly assumed
typescript-language-server is absent from the host PATH; they now pass an empty
PATH so resolution is deterministic regardless of the developer's machine.

Verification

  • normalizeDiagnosticUri unit tests: Windows didOpen/publish URIs match,
    drive-only lowering preserves path case, POSIX URIs unchanged and
    non-colliding (red before fix, green after)
  • end-to-end against typescript-language-server on Windows: a file with three
    type errors returned 0 diagnostics before, 4 after
  • npx vitest run: 32 passed, 1 skipped
  • npx tsc --noEmit: clean
  • npx biome check: clean

Summary by cubic

Fixes missing diagnostics on Windows by normalizing file URIs so publishDiagnostics entries match lookups. Also makes Windows spawn-command tests deterministic.

  • Bug Fixes
    • Added normalizeDiagnosticUri to reconcile Windows drive prefixes (file:///C:/ vs file:///c%3A/); lowers only the drive letter, preserves path case, and runs only on Windows.
    • Applied normalization when writing and reading from the diagnostics store.
    • Stabilized Windows createSpawnCommand tests by passing empty PATH and PATHEXT.

Written for commit 33f819e. Summary will update on new commits.

Review in cubic

@bskim
bskim requested a review from code-yeongyu as a code owner June 25, 2026 11:23
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.

1 participant