astral-sh/ruff · error · anyhow::Error
Workspace URI is not a file path
Error message
Workspace URI is not a file path: {uri} What it means
`Session::remove_workspace_folder` handles the `workspace/didChangeWorkspaceFolders` removal notification. It converts the workspace folder URI to a filesystem path via `Uri::to_file_path()`, and fails with this error when the URI does not denote a file-system path (e.g. a remote/virtual scheme). ty only supports local file-path workspaces, so non-`file://` URIs cannot be registered or removed as workspace folders.
Solutions
- Ensure the workspace root ty is opened with is backed by a real local `file://` path
- If working remotely, run the ty server on the remote machine (remote extension) so URIs resolve locally there
- Skip sending workspace-folder removal events for virtual/untitled folders
- Convert or map virtual URIs to local file paths before forwarding the notification to ty
Example fix
// before: sending a remote workspace removal
{"event":{"removed":[{"uri":"vscode-remote://ssh-remote%2Bhost/home/project"}]}}
// after: use the local path as seen by the server
{"event":{"removed":[{"uri":"file:///home/user/project"}]}} Defensive patterns
Strategy: validation
Validate before calling
// Only forward removals for file-scheme workspace folders
function isFileUri(uri) {
try {
const u = new URL(uri);
return u.protocol === 'file:' && u.pathname !== '' && u.pathname !== '/';
} catch (e) { return false; }
}
removedFolders.filter(f => isFileUri(f.uri)).forEach(sendRemovalToTy); Type guard
function isFilePathWorkspaceFolder(f) {
return typeof f === 'object' && f !== null
&& typeof f.uri === 'string'
&& f.uri.startsWith('file://')
&& f.uri.length > 'file://'.length;
} Try / catch
// Catch and report non-file workspace URIs before they reach ty
try {
tyClient.removeWorkspaceFolder(folder);
} catch (err) {
if (/not a file path/i.test(err.message)) {
console.warn('Skipping non-file workspace folder: ' + folder.uri);
} else { throw err; }
} Prevention
- Open ty workspaces only on local `file://` directories
- For remote/container development, run the ty server inside the remote environment
- Filter out untitled/virtual folders from workspace-folder change events
- Map bridged URI schemes back to local paths at the client adapter layer
When it happens
Trigger: The client sends `workspace/didChangeWorkspaceFolders` removing a folder whose URI is not convertible to a path - e.g. `untitled:`, `remote://`, `vscode-remote://`, `zip:` or any virtual document scheme.
Common situations: Using ty over a remote-SSH / container / web extension where workspace folders use `vscode-remote://` URIs; clients that open untitled (unsaved) workspace roots; forwarding the LSP through a bridge that rewrites URIs to non-file schemes.
Related errors
- Failed to convert workspace URI to file path
- Tried to remove non-existent workspace URI
- -32603
- Attempted to add edits for a document that was already…
- client exited without proper shutdown sequence
AI-assisted analysis of astral-sh/ruff@5bb508f594 (2026-09-05).
Data as JSON: /api/errors/d75fb98e3235e26e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/ty_server/src/session.rs:994
/// Removes a workspace folder at the given URI.
///
/// This removes the workspace folder and its associated project database,
/// and clears diagnostics for any documents that were in the workspace.
///
/// # Errors
///
/// This returns an error if the workspace folder has already been removed
/// or otherwise could not be found.
pub(crate) fn remove_workspace_folder(
&mut self,
client: &Client,
uri: &Uri,
) -> anyhow::Result<()> {
tracing::info!("Removing workspace folder: {uri}");
let path = uri
.to_file_path()
.map_err(|()| anyhow!("Workspace URI is not a file path: {uri}"))?;
let workspace_path = SystemPathBuf::from_path_buf(path)
.map_err(|path| anyhow!("Workspace path is not valid UTF-8: {}", path.display()))?;
anyhow::ensure!(
self.workspaces.unregister(&workspace_path),
"Workspace not found: {uri}",
);
// Note that it is somewhat unclear whether we actually need to
// clear diagnostics here. It seems that, at least in the case
// of VS Code, it will auto-clear any diagnostics not found in
// the workspace diagnostic response. Moreover, VS Code will
// re-request workspace diagnostics after removing a workspace
// folder.
//
// For now, we keep unconditionally clearing diagnostics on
// opened text documents for reasons of good sense, but it's
// possible that we don't even need to do that (when workspaceView on GitHub (pinned to 5bb508f594)