Memory tool: user memory is never auto-loaded when the memories directory is a junction/symlink (strict FileType check)
- Dominant language
- TypeScript
- Stars
- 193k
- Forks
- 42.4k
- PR merge metrics
- PR metrics pending
Description
Does this issue occur when all extensions are disabled?: N/A — the memory tool ships as the built-in `copilot` extension, so chat is unavailable with `--disable-extensions`. No third-party extension is involved; the defect is in the bundled extension's own code (quoted below).
- VS Code Version: 1.130.0
- OS Version: Windows 11 Enterprise x64 (10.0.26200)
## Summary
`` is always reported as empty when
`globalStorage/github.copilot-chat/memory-tool/memories` is an NTFS **junction**
(or a symlinked directory), even though the directory contains many valid memory files.
Per the [documentation](https://code.visualstudio.com/docs/agents/memory),
"the first 200 lines are automatically loaded into the agent's context at the start
of every session." This never happens in the above configuration.
The failure is **asymmetric**, which makes it hard to notice:
| Path | Works? |
|---|---|
| Writing memories via the `memory` tool | Yes |
| Reading / listing via the `memory` tool | Yes |
| `Chat: Show Memory Files` command | Yes — lists every file |
| Automatic injection into `` | **No — always empty** |
So the UI and the tools both indicate that memory exists, while the agent never
actually receives it.
## Root cause
In `resources/app/extensions/copilot/dist/extension.js`, `getUserMemoryContent()`:
```js
async getUserMemoryContent() {
let t = this.extensionContext.globalStorageUri;
if (!t) return;
let r = ae.joinPath(t, "memory-tool/memories");
try {
if ((await this.fileSystemService.stat(r)).type !== 2) return; // <-- here
} catch { return }
...
}
```
`FileType` is a bitmask. A plain directory reports `Directory` (2), but a junction /
symbolic link reports `Directory | SymbolicLink` (2 | 64 = 66). The strict `!== 2`
comparison therefore returns early and user memory is silently treated as
non-existent.
The same strict check appears in `getSessionMemoryFiles()` and
`getLocalRepoMemoryFiles()`, so session and repo memory are presumably affected the
same way.
Steps to Reproduce:
1. Create a real directory to hold the memories, e.g. `D:\memories-store`, and put a
small valid memory file in it — `test.md` containing
`- remember: the magic token is ABC123`.
2. Replace the memories directory with a junction pointing at it (run in PowerShell,
with VS Code closed):
```powershell
$mt = "$env:APPDATA\Code\User\globalStorage\github.copilot-chat\memory-tool"
Remove-Item "$mt\memories" -Recurse -Force
New-Item -ItemType Junction -Path "$mt\memories" -Target "D:\memories-store"
```
3. Start VS Code and open a new chat session.
4. Send this prompt: `Answer without using any tools. Paste the contents of your block verbatim.`
5. Run `Chat: Show Memory Files` from the Command Palette and compare.
### Expected
`` contains `## test.md` followed by the note body.
### Actual
`` contains:
```
No user preferences or notes saved yet. Use the memory tool to store persistent notes under /memories/.
```
…while `Chat: Show Memory Files` lists `test.md` correctly and the `memory` tool can
read it, confirming the files are reachable. Only the auto-load path fails.
Replacing the junction with a plain directory containing the same files is the only
workaround.
## Suggested fix
Use a bitmask test instead of strict equality, in all three functions:
```js
const st = await this.fileSystemService.stat(r);
if ((st.type & FileType.Directory) === 0) return;
```
## Why this matters
Sharing one memory store across Copilot surfaces (VS Code, Copilot CLI, Copilot
Desktop) is naturally done with a junction/symlink, because each surface reads a
different fixed path. With this bug that configuration silently disables user memory
in VS Code, and because both the UI and the tools keep reporting that memory exists,
the user gets no signal that their stored preferences are never applied.
## Related
- #323174 — always-loaded memory context cost (the 200-line aggregate cap)
- #304101 — user-level `.instructions.md` discovered but not auto-applied (similar
"visible in the UI but not injected" class of problem)
Contributor guide
Assessment
This issue has not been assessed yet.