uutils/coreutils · error · clap::Error
InvalidUtf8
Error message
InvalidUtf8
What it means
ShortcutValueParser::parse_ref requires the raw OsStr value to be valid UTF-8 before doing prefix matching against possible values; otherwise it returns clap::ErrorKind::InvalidUtf8. Clap's typed value parsers reject non-UTF-8 arguments by default.
Solutions
- Ensure the argument is valid UTF-8 before invoking (e.g. iconv or validate in the script)
- If you control the parser, use a lossy conversion or an OsStr-based matcher instead of to_str()
- Catch the clap error and surface a clear message to the user
Example fix
// before
let value = raw_os_str;
// after
let value = raw_os_str.to_str().ok_or_else(|| anyhow!("value must be UTF-8"))?; Defensive patterns
Strategy: type-guard
Validate before calling
fn is_utf8(v: &std::ffi::OsStr) -> bool { v.to_str().is_some() } Type guard
fn as_utf8(v: &std::ffi::OsStr) -> Option<&str> { v.to_str() } Try / catch
match parse_ref(cmd, arg, os_value) {
Err(e) if e.kind() == clap::error::ErrorKind::InvalidUtf8 => eprintln!("argument must be valid UTF-8"),
r => r?,
} Prevention
- Sanitize environment variables containing raw bytes before passing them as CLI args
- Convert incoming data to UTF-8 (with lossy replacement) at ingestion points
- Avoid `ls | xargs` pipelines over non-UTF-8 filenames
When it happens
Trigger: Passing an argument containing invalid UTF-8 bytes (e.g. from a shell variable with raw bytes) to a CLI option backed by this parser; also reproduced in the unit tests with non-UTF-8 input.
Common situations: Filenames with Latin-1 or arbitrary bytes passed as option values; scripts importing data from systems with different encodings.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid value
- csplit-stream-not-utf8
- InvalidUtf8 clap error for non-UTF-8 argument value
- InvalidValue clap error for unmatched argument value
- mv-error-backup-might-destroy-source
AI-assisted analysis of uutils/coreutils@92995feca2 (2026-09-20).
Data as JSON: /api/errors/05dcfbb853b14df8.
Report an issue: GitHub.
Appendix: source
Thrown at src/uucore/src/lib/features/parser/shortcut_value_parser.rs:100
ContextValue::StyledStrs(vec![format!(
"It looks like '{value}' could match several values. Did you mean {formatted_possible_values}?"
)
.into()]),
);
}
impl TypedValueParser for ShortcutValueParser {
type Value = String;
fn parse_ref(
&self,
cmd: &clap::Command,
arg: Option<&clap::Arg>,
value: &std::ffi::OsStr,
) -> Result<Self::Value, clap::Error> {
let value = value
.to_str()
.ok_or(clap::Error::new(ErrorKind::InvalidUtf8))?;
let matched_values: Vec<_> = self
.0
.iter()
.filter(|x| x.get_name_and_aliases().any(|name| name.starts_with(value)))
.collect();
match matched_values.len() {
0 => Err(self.generate_clap_error(cmd, arg, value, &[])),
1 => Ok(matched_values[0].get_name().to_string()),
_ => {
if let Some(direct_match) = matched_values.iter().find(|x| x.get_name() == value) {
Ok(direct_match.get_name().to_string())
} else {
Err(self.generate_clap_error(cmd, arg, value, &matched_values))
}
}
}View on GitHub (pinned to 92995feca2)