{"record":{"id":"fccf6f9c3dfc5e38","repo":"astral-sh/ruff","slug":"workspace-uri-is-not-valid-utf8","errorCode":null,"errorMessage":"Workspace URI is not valid UTF8","messagePattern":"Workspace URI is not valid UTF8","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ty_server/src/session.rs","lineNumber":1543,"sourceCode":"    ///\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)\n    }\n\n    /// Unregisters a workspace folder at the given path.\n    ///","sourceCodeStart":1525,"sourceCodeEnd":1561,"githubUrl":"https://github.com/astral-sh/ruff/blob/672bb4edf04c84f8b0753346359daee4057158f2/crates/ty_server/src/session.rs#L1525-L1561","documentation":"During workspace registration, the URI converted to an OS path but that path is not valid UTF-8, so SystemPathBuf::from_path_buf fails (session.rs:1543). The code comment notes this is considered near-impossible because the path came from a Uri, but percent-encoded non-UTF-8 bytes can still produce it.","triggerScenarios":"Adding a workspace folder whose decoded path bytes are invalid UTF-8 — practically only reachable via URIs percent-encoded from raw non-UTF-8 filenames.","commonSituations":"Legacy-encoded project directories on Linux, files created by old tools with locale-encoded names, or synthetic URIs constructed from raw OS paths.","solutions":["Rename the directory to a UTF-8 name before opening it as a workspace","Run the editor under a UTF-8 locale so it generates UTF-8 URIs","Skip adding the offending folder and open a differently-located copy"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// TS: skip folders whose decoded path is not valid UTF-8\nconst decodes = (uri: vscode.Uri): boolean => {\n  try { Buffer.from(uri.fsPath, 'utf8'); return !uri.fsPath.includes('\\uFFFD'); }\n  catch { return false; }\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep workspace root paths strictly UTF-8","Prefer renaming over trying to paper over encoding in URIs","This failure is near-unreachable via normal editors — hitting it means hand-built URIs from raw bytes"],"tags":["lsp","workspace","uri","unicode","encoding"],"backgroundTag":null,"analyzedSha":"672bb4edf04c84f8b0753346359daee4057158f2","analyzedAt":"2026-08-16T08:54:05.464Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}