Skip to content

fix: check POSIX absolute path before Win32 in resolveSymlinks#75

Open
laplaque wants to merge 1 commit intojacksteamdev:mainfrom
laplaque:fix/resolve-symlinks-posix-path
Open

fix: check POSIX absolute path before Win32 in resolveSymlinks#75
laplaque wants to merge 1 commit intojacksteamdev:mainfrom
laplaque:fix/resolve-symlinks-posix-path

Conversation

@laplaque
Copy link
Copy Markdown

@laplaque laplaque commented Apr 2, 2026

Summary

Fixes #36 — duplicate /home/<user> in server install path on Linux/macOS/WSL.

Root cause: path.win32.isAbsolute() returns true for POSIX absolute paths (a leading / is treated as the current drive root in Win32). Since it was checked first in the if/else-if chain, path.posix.isAbsolute() was never reached on non-Windows platforms. This caused the root segment to be set to "" instead of "/", producing a relative path. realpath then resolved it against CWD, prepending the home directory on every path component — and compounding with each settings panel open or install attempt.

Fix: Swap the if/else-if order so path.posix.isAbsolute() is checked first. This is a one-line logic change (plus explanatory comments) with no behavioral impact on Windows, where path.posix.isAbsolute() returns false for drive-letter paths like C:\....

Note on existing PRs

PRs #45 and #52 address the same issue with a post-hoc removeDuplicatePathSegments() function. This PR instead fixes the root cause directly, avoiding the need for path deduplication heuristics.

Test plan

  • Verify server install works on Linux/WSL with a vault path like /home/user/vault
  • Verify server install still works on Windows with drive-letter paths
  • Verify server install still works on macOS
  • Verify symlinked vault paths still resolve correctly

path.win32.isAbsolute() returns true for POSIX absolute paths
(a leading "/" is treated as the current drive root), so checking
it first causes the root segment to be set to "" instead of "/".
This produces a relative path, and realpath then resolves it
against CWD — prepending the home directory on every iteration.

Swapping the if/else-if order so path.posix.isAbsolute() is
checked first fixes the duplicate path issue on Linux/macOS/WSL.

Fixes jacksteamdev#36
@netlify
Copy link
Copy Markdown

netlify bot commented Apr 2, 2026

Deploy Preview for superb-starlight-b5acb5 canceled.

Name Link
🔨 Latest commit 3e084a6
🔍 Latest deploy log https://app.netlify.com/projects/superb-starlight-b5acb5/deploys/69ce59d491ada70008e2a1a5

istefox added a commit to istefox/obsidian-mcp-connector that referenced this pull request Apr 11, 2026
…cluster E)

Fix four related path-resolution bugs that combined to make the Linux
and WSL installation paths unusable and list_vault_files crash-prone
on some layouts:

1. POSIX-vs-Win32 absoluteness check order (PR jacksteamdev#75, laplaque)
   `path.win32.isAbsolute("/foo")` returns true because in Win32
   semantics a leading "/" is the root of the current drive. The
   previous code checked Win32 first, so on Linux / macOS / WSL it
   would push `parts[0]` (an empty string) instead of "/", producing
   a relative-looking path that made realpath prepend CWD repeatedly.
   Now checks POSIX first.

2. Duplicate path segments after symlink resolution (PR jacksteamdev#52, vanmarkic)
   On some iCloud Drive / symlinked vault layouts, `fsp.realpath`
   returns paths like `/home/user/home/user/vault` or
   `/Users/me/Library/Mobile Documents/Users/me/Library/Mobile
   Documents/vault`. These doubled paths broke the subsequent
   filesystem checks in getInstallationStatus. Added a new
   `removeDuplicatePathSegments()` helper in a dedicated module
   (`services/pathSegments.ts`) that walks the segment list and
   collapses any run matching the tail of what it has already
   accumulated. resolveSymlinks calls it after every successful
   realpath. Isolated in its own module so the pure logic is
   unit-testable without pulling in Obsidian imports.

3. Linux Claude Desktop config path (PR jacksteamdev#49, vanmarkic, issue jacksteamdev#31)
   Constants said `~/.config/claude/config.json`. Actual Claude
   Desktop Linux install uses `~/.config/Claude/claude_desktop_config.json`
   (capital C, full filename, matching macOS/Windows). Fixed.
   Also split the static path constants into a macro-free module
   (`constants/paths.ts`) so they can be imported from unit tests
   without triggering the `environmentVariables()` bundle-time macro.

4. Double slashes at vault root (PR jacksteamdev#53, vanmarkic)
   `list_vault_files` concatenated `args.directory` directly, so
   callers passing `"Documents/"` produced `/vault/Documents//` which
   Local REST API returns as HTTP 500. Now strips trailing slashes
   before composing the URL.

Adds three new test files:
- services/status.test.ts: 8 tests for removeDuplicatePathSegments
  (simple duplicate, multiple runs, multi-segment prefix, no-dup
  preservation, single-segment, similar-but-distinct, bare root,
  real-world iCloud case).
- constants/constants.test.ts: 12 tests for the platform constants
  (including explicit regression on the Linux capital-C fix).
- features/local-rest-api/pathNormalization.test.ts: 13 tests for
  the trailing-slash stripping logic in list_vault_files (single
  slash, multiple slashes, undefined, nested paths, vault-boundary
  double-slash prevention).

Total: 33 new tests across server + plugin packages. Plugin went from
0 tests to 20.

Refs: jacksteamdev#31, jacksteamdev#36, jacksteamdev#37
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

[BUG] Download Path contains duplicate /home/<user>

2 participants