{"record":{"id":"5733ab8ceeb8566e","repo":"vercel/turborepo","slug":"clean-should-preserve-utf8-err","errorCode":null,"errorMessage":"clean should preserve utf8: {err:?}","messagePattern":"clean should preserve utf8: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/turborepo-paths/src/anchored_system_path_buf.rs","lineNumber":136,"sourceCode":"            .count();\n        #[cfg(windows)]\n        debug_assert!(\n            prefix_len >= 1,\n            \"Cannot traverse drives between {} and {}\",\n            start,\n            end\n        );\n\n        let traverse_count = these_components.len() - prefix_len;\n        // For every remaining non-matching segment in self, add a directory traversal\n        // Then, add every non-matching segment from other\n        let path = std::iter::repeat_n(Utf8Component::ParentDir, traverse_count)\n            .chain(other_components.into_iter().skip(prefix_len))\n            .collect::<Utf8PathBuf>();\n\n        let path: Utf8PathBuf = match path_clean::clean(path).try_into() {\n            Ok(path) => path,\n            Err(err) => panic!(\"clean should preserve utf8: {err:?}\"),\n        };\n\n        Self(path)\n    }\n\n    pub fn from_raw(raw: impl AsRef<str>) -> Result<Self, PathError> {\n        let system_path = raw.as_ref();\n        Ok(Self(system_path.into()))\n    }\n\n    pub fn as_str(&self) -> &str {\n        self.0.as_str()\n    }\n\n    /// Takes in a path, validates that it is anchored and constructs an\n    /// `AnchoredSystemPathBuf` with no trailing slashes.\n    pub fn from_system_path(path: &Path) -> Result<Self, PathError> {\n        let path = path","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/vercel/turborepo/blob/f9245100cf0d31d96628804ead485f6bf226e55a/crates/turborepo-paths/src/anchored_system_path_buf.rs#L118-L154","documentation":"While computing the relative path from one anchored path to another (emitting ../ for each unmatched leading segment, then the target segments), the result is cleaned and converted to a Utf8PathBuf. Since every input component is valid UTF-8 and path_clean does not change encoding, the \"clean should preserve utf8\" panic is an unreachable invariant guard.","triggerScenarios":"Internal bug or corrupted string data only; no caller input legitimately triggers it.","commonSituations":"Would appear only as a crash in turbo's relative-path computation after a regression.","solutions":["Upgrade turborepo","Report a minimal reproduction with the two paths involved if it recurs"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let rel = std::panic::catch_unwind(|| a.relative_to(&b));\nif let Ok(r) = rel { Ok(r) } else { Err(format!(\"cannot relativize {a} against {b}\")) }","preventionTips":["Report any reproduction with both path values — the invariant should never break","Pin turborepo versions in CI to bisect regressions quickly"],"tags":["rust","panic","path","invariant","utf8"],"backgroundTag":"path-invariant-panic","analyzedSha":"f9245100cf0d31d96628804ead485f6bf226e55a","analyzedAt":"2026-08-17T10:46:15.696Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}