Skip to content

fix: normalize path separators in WSL remote sessions - #229

Open
88871 wants to merge 1 commit into
pajoma:developfrom
88871:fix/wsl-path-normalization
Open

fix: normalize path separators in WSL remote sessions#229
88871 wants to merge 1 commit into
pajoma:developfrom
88871:fix/wsl-path-normalization

Conversation

@88871

@88871 88871 commented May 20, 2026

Copy link
Copy Markdown

Fixes #228

Problem

When vscode-journal is active in a WSL Remote VS Code session and the
configured journal base path is a Windows-style drive path (e.g.
C:\Users\<user>\Git\journal), the Journal: Today command opens an empty
editor at a malformed path like:

/C:\Users\<user>\Git\journal/2026/05/2026-05-18.md

The Windows drive path is concatenated with POSIX-style date components,
then vscode.Uri.file() prepends a / to make it absolute on Linux, producing
a path that does not exist.

Root cause

Path construction in TemplateService substitutes ${base} with the raw
value from getBasePath() and then calls Path.normalize() (the POSIX
path module on Linux). POSIX path.normalize does not treat \ as a
separator, so backslashes from the Windows-style config value survive intact
into the resolved path string.

Fix

Two-layer defence:

  1. conf.tsnormalizeBasePathForRuntime: the existing /mnt/<drive>/...
    mapping for explicit Windows drive paths is kept. Additionally, on non-Windows
    hosts any residual backslashes in non-drive paths (e.g. injected via
    ${workspaceFolder}) are now replaced with forward slashes before the value
    is returned from getBasePath().

  2. template-service.ts – after all template variables are substituted,
    replace any remaining \ characters with / on non-Windows hosts before
    Path.normalize() is called. This covers getResolvedEntryPath,
    getResolvedNotesPath, getResolvedWeeklyNotesPath, and getWeekPathPattern
    — every code path that produces a filesystem path for the active session.
    The ForLocalOpen variants are intentionally left unchanged because they
    intentionally preserve Windows-style paths for hand-off to the local client.

Result

With the fix, a configured base path of C:\Users\<user>\Git\journal in a
WSL remote session is first mapped to /mnt/c/Users/<user>/Git/journal by
normalizeBasePathForRuntime, and after date substitution and the backslash
guard in the template service the final path is a clean POSIX path such as:

/mnt/c/Users/<user>/Git/journal/2026/05/2026-05-18.md

No existing test assertions are changed; the fix is purely additive.

When the extension runs on a non-Windows host (WSL remote, SSH remote)
but the configured journal base path is a Windows-style drive path such
as C:\Users\...\journal, the path components were concatenated with a
mix of backslashes and forward slashes.  The result was a malformed path
like /C:\Users\...\journal/2026/05/20.md that VS Code could not resolve,
causing an empty buffer to be shown instead of the journal entry (pajoma#228).

Two-layer fix:

1. conf.ts – normalizeBasePathForRuntime: besides the existing /mnt/<drive>/...
   conversion for explicit Windows drive paths, now also replaces stray
   backslashes in non-drive POSIX paths so that any Windows-style separator
   that slipped in via ${workspaceFolder} or similar variables is cleaned up
   before the path is returned from getBasePath().

2. template-service.ts – getResolvedEntryPath / getResolvedNotesPath /
   getResolvedWeeklyNotesPath / getWeekPathPattern: after all template
   variables are substituted, replace any remaining backslashes with forward
   slashes on non-Windows hosts before Path.normalize() runs.  This acts as
   a belt-and-suspenders guard so that a Windows-style base path that somehow
   passes through getBasePath() unchanged cannot corrupt the final resolved
   path string.
@88871
88871 force-pushed the fix/wsl-path-normalization branch from 4beac2d to 8f0c18a Compare May 20, 2026 02:49

@pajoma pajoma left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for the contribution and the detailed PR description.

Before this can merge, tests are required. The bug is in a platform-specific code path that is easy to cover with plain Node (no VS Code needed):

normalizeBasePathForRuntime must have unit tests covering at minimum:

  • C:\Users\foo\journal/mnt/c/Users/foo/journal
  • /C:\Users\foo\journal (leading slash, as observed in the bug) → /mnt/c/Users/foo/journal
  • /mnt/c/Users/foo/journal (already POSIX) → unchanged
  • mixed-separator non-drive path (e.g. foo\bar/baz) → backslashes replaced

Without tests, any future refactor of this function or the surrounding getBasePath logic will have no safety net, and the exact scenario from the issue (mixed slashes, leading slash before drive letter) could regress silently.

Additional concerns noted in review (not blockers on their own, but worth addressing):

  • The backslash guards added to template-service.ts are redundant — getBasePath() already calls normalizeBasePathForRuntime(), so by the time ${base} is substituted, no backslash survives. The fix should live in conf.ts only.
  • PR description states "Detection uses both process.platform and vscode.env.remoteName" — the code only uses process.platform. Please correct the description.
  • The /mnt/<drive> mapping is WSL-specific. The description claims coverage for "WSL/SSH/containers" but a plain SSH remote to a Linux host would get a nonsensical /mnt/c/... path. Please narrow the claim or gate the /mnt mapping on vscode.env.remoteName === 'wsl'.

Happy to iterate once tests are in place.

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.

WSL remote: 'today' opens empty page with malformed mixed-slash path

2 participants