AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

FilesystemFileSearchMiddleware Returns Windows Separators In Virtual Paths

On Windows, FilesystemFileSearchMiddleware returns virtual paths containing native backslashes (e.g., '/src\\nested\\example.py') instead of the contract's forward-slash format, causing inconsistent and non-portable tool outputs.

mediumConfidence 95%LangchainAffected V1.3.18

Origin Analysis

The glob, ripgrep, and Python fallback result-building code uses `str(path.relative_to(root_path))`, which on Windows produces backslash separators because `str(Path)` uses the host OS separator. These relative paths are then prefixed with '/' to form virtual paths, resulting in mixed separators.
On Windows, create a temporary directory with a nested file, instantiate FilesystemFileSearchMiddleware with root_path, invoke glob_search with pattern '**/*.py' and grep_search with pattern matching the file, then assert the result equals '/src/nested/example.py'; the assertion fails and prints paths with backslashes.

Fixing Code Block

from pathlib import Path # Add this helper method to FilesystemFileSearchMiddleware: def _to_virtual_path(self, path: Path) -> str: """Return a POSIX-style virtual path relative to root_path.""" return "/" + path.relative_to(self.root_path).as_posix() # Then replace the three result-building expressions that currently use # f"/{path.relative_to(self.root_path)}" with self._to_virtual_path(path): # 1) glob search return "\n".join( self._to_virtual_path(p) for p in matches ) # 2) ripgrep parser return "\n".join( self._to_virtual_path(Path(item["path"])) for item in parsed ) # 3) Python grep fallback return "\n".join( self._to_virtual_path(path) for path in matched_files )
Using `Path.as_posix()` converts the relative path to a string with forward slashes regardless of the host OS. The helper centralizes the conversion and ensures all emitted virtual paths follow the POSIX separators contract without changing the public API or adding dependencies.

Edge Case Audit

This change normalizes output only; it has no concurrency or threading implications. On Windows, any downstream code that incorrectly relied on the previous backslash format could break, but the documented contract expects forward slashes. Rollback is straightforward: revert the three expressions to the original `str(path.relative_to(root_path))` form. No version-specific or cross-platform regressions are expected because `as_posix()` is a no-op on POSIX systems.

Ecosystem Topology