rust-lang/cargo · error
must be utf-8 in toml
Error message
must be utf-8 in toml
What it means
This panic is in BuildTargetConfig::values(), which resolves build.target config entries. When a target string ends with .json (a custom target spec file path), cargo joins the config definition root with the path and calls .to_str().expect("must be utf-8 in toml"). The invariant is that since the value originated from a TOML string (always UTF-8) and the cwd/root is also expected to be UTF-8, the joined path should be UTF-8.
Source
Thrown at src/context/schema.rs:288
.string(|one| Ok(BuildTargetConfigInner::One(one.to_owned())))
.seq(|many| many.deserialize().map(BuildTargetConfigInner::Many))
.deserialize(deserializer)
}
}
impl BuildTargetConfig {
/// Gets values of `build.target` as a list of strings.
pub fn values(&self, cwd: &Path) -> CargoResult<Vec<String>> {
let map = |s: &String| {
if s.ends_with(".json") {
// Path to a target specification file (in JSON).
// <https://doc.rust-lang.org/rustc/targets/custom.html>
self.inner
.definition
.root(cwd)
.join(s)
.to_str()
.expect("must be utf-8 in toml")
.to_string()
} else {
// A string. Probably a target triple.
s.to_string()
}
};
let values = match &self.inner.val {
BuildTargetConfigInner::One(s) => vec![map(s)],
BuildTargetConfigInner::Many(v) => v.iter().map(map).collect(),
};
Ok(values)
}
}
/// The `[resolver]` table.
///
/// Example configuration:
///View on GitHub (pinned to 0e07a15537)
Solutions
- Use an absolute path for the .json target spec file to avoid joining with a non-UTF-8 cwd.
- Ensure the working directory and all ancestor paths are valid UTF-8.
- Set locale environment variables (LANG, LC_ALL) to a UTF-8 encoding like en_US.UTF-8.
Example fix
// before
.join(s).to_str().expect("must be utf-8 in toml").to_string()
// after
.join(s).to_str().map(|s| s.to_string())
.ok_or_else(|| anyhow::format_err!("build.target path `{}` is not valid UTF-8", s))? Defensive patterns
Strategy: validation
Validate before calling
// Ensure cwd is UTF-8 before building with build.target = "*.json"
let cwd = std::env::current_dir()?;
if cwd.to_str().is_none() {
return Err("working directory is not valid UTF-8; build.target .json paths may fail".into());
} Type guard
fn is_utf8_path(path: &std::path::Path) -> bool {
path.to_str().is_some()
} Prevention
- Keep project directories and all ancestor paths as valid UTF-8.
- Set LANG and LC_ALL to a UTF-8 locale (e.g., en_US.UTF-8).
- Use absolute UTF-8 paths for build.target .json files in config.
When it happens
Trigger: Setting build.target to a .json path in config while the working directory or config file location contains non-UTF-8 bytes (e.g., on Linux with a non-UTF-8 locale or a directory name with invalid byte sequences). The path join introduces the non-UTF-8 component.
Common situations: Running cargo on a system with a non-UTF-8 locale (LC_ALL, LANG set to legacy encodings); a project directory path containing non-UTF-8 characters; referencing a target spec JSON file via a relative path that traverses a non-UTF-8 directory.
Related errors
- already loaded config values
- len() == 1 above
- remote registries must have config
- artifact-dir was not locked
- artifact dep
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/12d1ae467f4a0dbc.json.
Report an issue: GitHub.