uutils/coreutils · error · clap::Error

InvalidUtf8 clap error for non-UTF-8 argument value

Error message

InvalidUtf8 clap error for non-UTF-8 argument value

What it means

In `ShortcutValueParser::parse_ref`, the input `OsStr` value is converted with `to_str()`; if it isn't valid UTF-8, a clap `ErrorKind::InvalidUtf8` error is raised immediately, since prefix matching against possible values requires a `&str`.

Source

Thrown at src/uucore/src/lib/features/parser/shortcut_value_parser.rs:99

        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 325183372a)

Solutions

  1. Pass valid UTF-8 values for the option
  2. Re-encode the source data to UTF-8 before passing it
  3. If the option must accept arbitrary bytes, this parser is the wrong choice for that argument

Example fix

# before
prog --mode "$(printf '\xff\xfe')"
# after
prog --mode "fast"
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_utf8(v: &std::ffi::OsStr) -> bool { v.to_str().is_some() }
if !is_valid_utf8(value) {
    eprintln!("argument value must be valid UTF-8");
    std::process::exit(2);
}

Type guard

fn as_utf8(v: &std::ffi::OsStr) -> Option<&str> { v.to_str() }

Try / catch

match parse_arg(os_value) {
    Err(e) if e.kind() == clap::error::ErrorKind::InvalidUtf8 => {
        eprintln!("non-UTF-8 value supplied");
        clap::Error::new(e.kind()).exit()
    }
    other => other?,
}

Prevention

When it happens

Trigger: Supplying an argument value containing non-UTF-8 bytes (e.g. from binary data or a filename with invalid encoding) to an option parsed by ShortcutValueParser.

Common situations: Shells passing raw bytes from files/commands (`--opt "$(cat binfile)"`), locales/encodings producing non-UTF-8 argument bytes, fuzzing.

Related errors


AI-assisted analysis of uutils/coreutils@325183372a (2026-08-31). Data as JSON: /api/errors/1a7563cfb7750ec3. Report an issue: GitHub.