Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/web
Steps to reproduce
- Open a thread whose workspace is
/home/me/project. - Create a file in a sibling folder, for example
/home/me/other/notes.md. - Have the agent mention it with a parent-folder path, as a markdown link
[notes.md](../other/notes.md)or as inline code../other/notes.md. - Click the chip.
Expected behavior
The file opens read-only in the file viewer, the same as it does when the agent writes /home/me/other/notes.md or ~/other/notes.md.
Actual behavior
The file viewer shows:
Failed to read workspace file '../other/notes.md' in '/home/me/project'.
The chip tooltip shows /home/me/project/../other/notes.md. The absolute form and the ~/ form of the same file open correctly in the same message.
Impact
Minor bug or occasional failure
Version or commit
main @ 68e50db
Environment
Windows desktop app with the server in WSL2, Ubuntu 24.04. The cause is in shared web code, so I do not think it is specific to WSL.
Cause
resolvePathLinkTarget in apps/web/src/terminal-links.ts joins the path to the workspace root and keeps the .. segment. The result, /home/me/project/../other/notes.md, still starts with the workspace root. workspaceRelativeFilePath compares by string prefix, so it classifies the file as a workspace file with the relative path ../other/notes.md. The server refuses a relative path that leaves the workspace. An absolute path would have been read as a host file.
Mobile already guards against this. resolveWorkspaceRelativeFilePath in apps/mobile/src/features/files/filePath.ts has the comment "/repo/../x starts with the root but escapes it".
Related issues
- [Bug]: File chips for files created outside the project root fail to open: "Failed to read workspace file 'docs/X.md' in '<root>'" #8251 has the same error text and a different cause. There the path has no
..and the agent worked in a different folder from the project root. - [Bug]: A chat link to a folder outside the workspace opens a failing file preview #15215 is about a link to a folder outside the workspace. Links to files there open correctly.
Proposed fix
Collapse . and .. segments in resolvePathLinkTarget before the workspace check. A file outside the workspace then opens read-only as a host file. A ../ link that stays inside the workspace, such as a link between two docs folders, still opens as a workspace file.
I have this fix with focused tests in terminal-links.test.ts and markdown-links.test.ts. I can open a PR if the direction is right.
Workaround
Ask the agent to write the absolute path.
Investigated with Claude Code, Opus 5.5.
Activity
juliusmarminge commentedon Oct 6, 2026
Note
Grok responding on behalf of Julius.
Triage
Thanks again for another precise report, @genericrohan! This matches what we see in the web file-link resolver. It's separate from #8251 (a relative path without
..resolved against a project root that isn't the agent's working directory) and #15215 (links to folders outside the workspace).What I found
resolvePathLinkTargetinapps/web/src/terminal-links.tsjoins a relative link onto the workspace root and leaves.and..in the string. For[notes.md](../other/notes.md)with root/home/me/project, the chip target becomes/home/me/project/../other/notes.md, which is also what the tooltip shows.workspaceRelativeFilePathonly checks that the string starts with the root, so it treats this as the workspace-relative path../other/notes.md. The server'sresolveRelativePathWithinRootrejects that, and the viewer showsFailed to read workspace file '../other/notes.md' in '/home/me/project'.~/paths never get the root prefix, so they open read-only as host files. An absolute link that still contains..(e.g./home/me/project/../other/notes.md) fails the same way, since it's returned unchanged and still starts with the root.Likely fix area
Your proposal of collapsing
.and..before the workspace check fits the code. A few details that may matter there:realpath) and apply it to the path only, preserving any:line/:columnsuffix, and expanding~/before collapsing.docs/guide/../readme.mdshould stay a workspace file. The mobile check inapps/mobile/src/features/files/filePath.tstreats every..after the root as outside, which would misclassify that case.terminal-links.test.tsandmarkdown-links.test.tsare natural places to cover the outside-workspace case, an in-workspace..link, and a line suffix.A maintainer will decide on the fix direction.
Add captures for pingdotgg#16354
Add captures for pingdotgg#16354
Add captures for pingdotgg#16354