vercel/turborepo · critical

clean should produce valid UTF-8: {err:?}

Error message

clean should produce valid UTF-8: {err:?}

What it means

AbsoluteSystemPathBuf::from_unknown resolves a possibly-relative path against a base directory, cleans it, and converts the cleaned std Path into a Utf8PathBuf. Inputs are already Utf8PathBuf (valid UTF-8 by construction) and path cleaning preserves encoding, so the "clean should produce valid UTF-8" panic is unreachable absent an internal bug.

Source

Thrown at crates/turborepo-paths/src/absolute_system_path_buf.rs:94

    }

    /// Takes in a system path of unknown type. If it's absolute, returns the
    /// path, If it's relative, appends it to the base after cleaning it.
    pub fn from_unknown(base: &AbsoluteSystemPath, unknown: impl Into<Utf8PathBuf>) -> Self {
        // we have an absolute system path and an unknown kind of system path.
        let unknown: Utf8PathBuf = unknown.into();
        if unknown.is_absolute() {
            Self(unknown)
        } else {
            let path = match base
                .as_path()
                .join(unknown)
                .as_std_path()
                .clean()
                .try_into()
            {
                Ok(path) => path,
                Err(err) => panic!("clean should produce valid UTF-8: {err:?}"),
            };
            Self(path)
        }
    }

    pub fn from_cwd(unknown: impl Into<Utf8PathBuf>) -> Result<Self, PathError> {
        let cwd = Self::cwd()?;
        Ok(Self::from_unknown(&cwd, unknown))
    }

    pub fn cwd() -> Result<Self, PathError> {
        // TODO(errors): Unwrap current_dir()
        Ok(Self(Utf8PathBuf::try_from(std::env::current_dir()?)?))
    }

    /// Anchors `path` at `self`.
    ///
    /// # Arguments

View on GitHub (pinned to f9245100cf)

Solutions

  1. Upgrade turborepo
  2. Prefer checked constructors (from_cwd, try_from) over any unsafe/unchecked creation of these path types
  3. Report a reproduction if it persists
Defensive patterns

Strategy: fallback

Try / catch

let resolved = std::panic::catch_unwind(|| {
    AbsoluteSystemPathBuf::from_unknown(&base, relative)
});
let path = resolved.unwrap_or_else(|_| AbsoluteSystemPathBuf::from(base.join(relative)));

Prevention

When it happens

Trigger: No legitimate trigger; would require the UTF-8 invariant of the types to be broken already (unsafe construction or memory corruption).

Common situations: Not observed in practice; would surface as an abort during path resolution inside turbo.

Related errors


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