vercel/turborepo · critical

clean should preserve utf8: {err:?}

Error message

clean should preserve utf8: {err:?}

What it means

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.

Source

Thrown at crates/turborepo-paths/src/anchored_system_path_buf.rs:136

            .count();
        #[cfg(windows)]
        debug_assert!(
            prefix_len >= 1,
            "Cannot traverse drives between {} and {}",
            start,
            end
        );

        let traverse_count = these_components.len() - prefix_len;
        // For every remaining non-matching segment in self, add a directory traversal
        // Then, add every non-matching segment from other
        let path = std::iter::repeat_n(Utf8Component::ParentDir, traverse_count)
            .chain(other_components.into_iter().skip(prefix_len))
            .collect::<Utf8PathBuf>();

        let path: Utf8PathBuf = match path_clean::clean(path).try_into() {
            Ok(path) => path,
            Err(err) => panic!("clean should preserve utf8: {err:?}"),
        };

        Self(path)
    }

    pub fn from_raw(raw: impl AsRef<str>) -> Result<Self, PathError> {
        let system_path = raw.as_ref();
        Ok(Self(system_path.into()))
    }

    pub fn as_str(&self) -> &str {
        self.0.as_str()
    }

    /// Takes in a path, validates that it is anchored and constructs an
    /// `AnchoredSystemPathBuf` with no trailing slashes.
    pub fn from_system_path(path: &Path) -> Result<Self, PathError> {
        let path = path

View on GitHub (pinned to f9245100cf)

Solutions

  1. Upgrade turborepo
  2. Report a minimal reproduction with the two paths involved if it recurs
Defensive patterns

Strategy: fallback

Try / catch

let rel = std::panic::catch_unwind(|| a.relative_to(&b));
if let Ok(r) = rel { Ok(r) } else { Err(format!("cannot relativize {a} against {b}")) }

Prevention

When it happens

Trigger: Internal bug or corrupted string data only; no caller input legitimately triggers it.

Common situations: Would appear only as a crash in turbo's relative-path computation after a regression.

Related errors


AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17). Data as JSON: /api/errors/5733ab8ceeb8566e. Report an issue: GitHub.