Bug Description
On Windows, if a project's configured path is on a mapped network drive (e.g. S:\ mapped to \server\share), the watch service throws a ValueError on every batch of file changes and
the entire watch cycle aborts - live sync never processes any changes for any project. Startup/initial sync works fine; only the live watch loop is affected.
Steps To Reproduce
- Install Basic Memory 0.22.1 on Windows (uv tool install basic-memory)
- Map a network share to a drive letter, e.g. net use S: \server\share
- Add a project whose path uses the drive letter, e.g. basic-memory project add notes S:\Notes
- Start the MCP server (basic-memory mcp) and modify any file inside the project
- See Watch service error during cycle with a ValueError traceback in the log, repeating on every change
Expected Behavior
File changes under the mapped-drive project are synced to the knowledge base, as they are for local-drive projects.
Actual Behavior
Every change batch raises, aborting the whole watch cycle (all projects):
ERROR | basic_memory.sync.watch_service:run:255 - Watch service error during cycle
...
File ".../basic_memory/sync/watch_service.py", line 375, in handle_changes
relative_path = Path(path).relative_to(directory).as_posix()
│ │ └ WindowsPath('//server/share/Notes')
│ └ 'S:/Notes\subdir\file.md.tmp.4648.fc05f140aea6'
File ".../pathlib/_local.py", line 385, in relative_to
raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
ValueError: 'S:\Notes\subdir\file.md.tmp...' is not in the subpath of '\\server\share\Notes'
Because the error fires before the .tmp filter (line 378), editor temp files trigger it constantly; the log grows by ~900 KB of repeated tracebacks per session.
Environment
- OS: Windows 11 Pro (10.0.26200)
- Python version: 3.13.11
- Basic Memory version: 0.22.1
- Installation method: uv tool
- Claude Desktop version: n/a (Claude Code MCP, stdio transport)
Additional Context
Project configured with a drive-letter path in config.json:
"notes": { "path": "S:\Notes", "mode": "local" }
Root cause in basic_memory/sync/watch_service.py, handle_changes():
directory = Path(project.path).resolve() # line 363
...
relative_path = Path(path).relative_to(directory).as_posix() # line 375
On Windows, Path.resolve() expands a mapped drive letter to its UNC form, so directory becomes \server\share\Notes. But path comes from watchfiles in the original drive-letter form
and is never resolved, so relative_to() always fails. The exception propagates through asyncio.gather in _watch_projects_cycle (line 175) and kills the cycle for all projects.
Possible Solution
Resolve the change path the same way the project directory is resolved:
relative_path = Path(path).resolve().relative_to(directory).as_posix()
(or normalize both sides with os.path.relpath). Note is_project_path() at line 339 already resolves both sides; handle_changes() only resolves one.
Bug Description
On Windows, if a project's configured path is on a mapped network drive (e.g. S:\ mapped to \server\share), the watch service throws a ValueError on every batch of file changes and
the entire watch cycle aborts - live sync never processes any changes for any project. Startup/initial sync works fine; only the live watch loop is affected.
Steps To Reproduce
Expected Behavior
File changes under the mapped-drive project are synced to the knowledge base, as they are for local-drive projects.
Actual Behavior
Every change batch raises, aborting the whole watch cycle (all projects):
ERROR | basic_memory.sync.watch_service:run:255 - Watch service error during cycle
...
File ".../basic_memory/sync/watch_service.py", line 375, in handle_changes
relative_path = Path(path).relative_to(directory).as_posix()
│ │ └ WindowsPath('//server/share/Notes')
│ └ 'S:/Notes\subdir\file.md.tmp.4648.fc05f140aea6'
File ".../pathlib/_local.py", line 385, in relative_to
raise ValueError(f"{str(self)!r} is not in the subpath of {str(other)!r}")
ValueError: 'S:\Notes\subdir\file.md.tmp...' is not in the subpath of '\\server\share\Notes'
Because the error fires before the .tmp filter (line 378), editor temp files trigger it constantly; the log grows by ~900 KB of repeated tracebacks per session.
Environment
Additional Context
Project configured with a drive-letter path in config.json:
"notes": { "path": "S:\Notes", "mode": "local" }
Root cause in basic_memory/sync/watch_service.py, handle_changes():
directory = Path(project.path).resolve() # line 363
...
relative_path = Path(path).relative_to(directory).as_posix() # line 375
On Windows, Path.resolve() expands a mapped drive letter to its UNC form, so directory becomes \server\share\Notes. But path comes from watchfiles in the original drive-letter form
and is never resolved, so relative_to() always fails. The exception propagates through asyncio.gather in _watch_projects_cycle (line 175) and kills the cycle for all projects.
Possible Solution
Resolve the change path the same way the project directory is resolved:
relative_path = Path(path).resolve().relative_to(directory).as_posix()
(or normalize both sides with os.path.relpath). Note is_project_path() at line 339 already resolves both sides; handle_changes() only resolves one.