jdx/mise · error

the prefix cannot be printed as a single UTF-8 path; use a…

Error message

the prefix cannot be printed as a single UTF-8 path; use a compatible prefix path

What it means

strict_package_root validates the `opt/<name>` record for an installed brew formula. It first checks that MISE_SYSTEM_BREW_PREFIX, when set, is representable as UTF-8, because the prefix path must be printable and passed to subprocesses/paths as a Rust str-backed Path. If the environment variable contains bytes that are not valid UTF-8 (e.g. invalid UTF-8 from a shell env), mise bails instead of guessing an encoding.

Solutions

  1. Unset or correct MISE_SYSTEM_BREW_PREFIX so it contains a valid UTF-8 absolute path (e.g. /home/linuxbrew/.linuxbrew)
  2. Print the variable to check it: `printf '%s' "$MISE_SYSTEM_BREW_PREFIX" | iconv -f utf-8 -t utf-8` — failure confirms invalid bytes
  3. Remove the override entirely to let mise use the default prefix

Example fix

// before
export MISE_SYSTEM_BREW_PREFIX=$'\xff/home/brew'  # invalid UTF-8
// after
export MISE_SYSTEM_BREW_PREFIX=/home/linuxbrew/.linuxbrew
Defensive patterns

Strategy: validation

Validate before calling

if (process.env.MISE_SYSTEM_BREW_PREFIX !== undefined) {
  Buffer.from(process.env.MISE_SYSTEM_BREW_PREFIX, 'utf8'); // throws on invalid encoding
}

Prevention

When it happens

Trigger: Setting MISE_SYSTEM_BREW_PREFIX to a value with non-UTF-8 bytes (e.g. via `env -i` scripts, raw byte export, or copy-pasted control characters) and then invoking anything that calls strict_package_root to resolve a package root.

Common situations: Container/CI images exporting env vars built from binary data; shells with locale mishandling producing invalid UTF-8 paths; accidentally setting the variable to a command's binary output.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/74200156535613ae. Report an issue: GitHub.

Appendix: source

Thrown at src/system/packages/brew/pour.rs:52

/// without it is a remnant of a failed install and must not block a retry.
pub(super) fn keg_installed(name: &str, pkg_version: &str) -> bool {
    keg_path(name, pkg_version).exists() && linked_version(name).as_deref() == Some(pkg_version)
}

/// the version `opt/<name>` points at, if the symlink resolves to an
/// existing keg
pub(super) fn linked_version(name: &str) -> Option<String> {
    let opt = prefix::prefix().join("opt").join(name);
    record_keg(name, &opt).map(|(version, _)| version)
}

/// Return the absolute opt path only when its symlink resolves to a keg directly inside the formula rack.
/// Preserve the configured prefix spelling and report invalid records without repairing them.
pub(super) fn strict_package_root(name: &str) -> Result<PathBuf> {
    if let Some(prefix) = std::env::var_os("MISE_SYSTEM_BREW_PREFIX")
        && prefix.to_str().is_none()
    {
        bail!("the prefix cannot be printed as a single UTF-8 path; use a compatible prefix path");
    }
    let prefix = prefix::prefix();
    let prefix = if prefix.is_absolute() {
        prefix
    } else {
        std::env::current_dir()
            .wrap_err_with(|| {
                format!(
                    "cannot resolve relative Homebrew prefix {}",
                    prefix.display()
                )
            })?
            .join(prefix)
    };
    let opt = prefix.join("opt").join(name);
    let rack = prefix.join("Cellar").join(name);
    let metadata =
        std::fs::symlink_metadata(&opt).map_err(|err| package_root_io_error(name, &opt, err))?;

View on GitHub (pinned to 533346cc37)