{"record":{"id":"da807f1a1b4cf296","repo":"astral-sh/ruff","slug":"workspace-uri-is-not-a-file-or-directory-uri","errorCode":null,"errorMessage":"Workspace URI is not a file or directory: {uri:?}","messagePattern":"Workspace URI is not a file or directory: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ty_server/src/session.rs","lineNumber":1539,"sourceCode":"}\n\nimpl Workspaces {\n    /// Registers a new workspace with the given URI and default settings for the workspace.\n    ///\n    /// This returns `true` when this workspace is added and `false`\n    /// when it has already been added.\n    ///\n    /// It's the caller's responsibility to later call\n    /// [`Session::request_uninitialized_workspace_folder_configurations`] with\n    /// the resolved settings for this workspace. Registering and initializing\n    /// a workspace is a two-step process because the workspace are announced\n    /// to the server during the `initialize` request, but the resolved\n    /// settings are only available after the client has responded to the\n    /// `workspace/configuration` request.\n    fn register(&mut self, uri: Uri) -> anyhow::Result<bool> {\n        let path = uri\n            .to_file_path()\n            .map_err(|()| anyhow!(\"Workspace URI is not a file or directory: {uri:?}\"))?;\n\n        // Realistically I don't think this can fail because we got the path from a Uri\n        let system_path = SystemPathBuf::from_path_buf(path)\n            .map_err(|_| anyhow!(\"Workspace URI is not valid UTF8\"))?;\n\n        if self.workspaces.contains_key(&system_path) {\n            return Ok(false);\n        }\n\n        self.workspaces.insert(\n            system_path,\n            Workspace {\n                uri,\n                settings: Arc::new(WorkspaceSettings::default()),\n                initialized: false,\n            },\n        );\n        Ok(true)","sourceCodeStart":1521,"sourceCodeEnd":1557,"githubUrl":"https://github.com/astral-sh/ruff/blob/672bb4edf04c84f8b0753346359daee4057158f2/crates/ty_server/src/session.rs#L1521-L1557","documentation":"When registering a workspace folder (from initialize's workspaceFolders or a later add), uri.to_file_path() failed, so the URI is not convertible to a filesystem path (session.rs:1539). Registration of that folder aborts; only file-scheme URIs are supported.","triggerScenarios":"Announcing a workspace folder with a non-`file:` URI — untitled:, vscode-remote with a non-file inner scheme, or virtual/remote document schemes lsp-types cannot convert.","commonSituations":"Browser-based or remote editors forwarding virtual workspaces, extensions adding synthesized folders, or clients passing rootUri in a non-file scheme.","solutions":["Filter initialize's workspaceFolders to `file://` URIs only","Fix the client to send real filesystem folders","For genuinely virtual workspaces, accept that ty cannot attach to them"],"exampleFix":"// before\nworkspaceFolders: [{ uri: 'untitled:Workspace-1', name: 'ws' }]\n\n// after\nworkspaceFolders: [{ uri: 'file:///home/me/project', name: 'project' }]","handlingStrategy":"type-guard","validationCode":"// TS: only announce convertible folders at initialize\nconst folders = vscode.workspace.workspaceFolders\n  ?.filter(f => f.uri.scheme === 'file')\n  .map(f => ({ uri: f.uri.toString(), name: f.name })) ?? [];","typeGuard":"const isFileWorkspaceFolder = (f: { uri: string | vscode.Uri }): boolean =>\n  (typeof f.uri === 'string' ? vscode.Uri.parse(f.uri) : f.uri).scheme === 'file';","tryCatchPattern":null,"preventionTips":["Filter initialize's workspaceFolders by scheme before sending","Don't forward virtual/remote workspace folders to ty — it is file-system based","Remember registration is two-step: register now, resolve configuration after workspace/configuration responds"],"tags":["lsp","workspace","uri","initialize"],"backgroundTag":null,"analyzedSha":"672bb4edf04c84f8b0753346359daee4057158f2","analyzedAt":"2026-08-16T08:54:05.464Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}