astral-sh/ruff · error · clap::Error

InvalidUtf8

InvalidUtf8

Error message

invalid UTF-8 was detected in one or more arguments

What it means

Rule-selector CLI options (--select, --ignore, --fixable, --unfixable and their --extend-* variants) use UnresolvedRuleSelectorParser, which converts the OsStr argument to str before parsing rule codes. Non-UTF-8 bytes fail the conversion and clap reports ErrorKind::InvalidUtf8.

Source

Thrown at crates/ruff_linter/src/rule_selector.rs:529

        type Parser = UnresolvedRuleSelectorParser;

        fn value_parser() -> Self::Parser {
            UnresolvedRuleSelectorParser
        }
    }

    impl TypedValueParser for UnresolvedRuleSelectorParser {
        type Value = UnresolvedRuleSelector;

        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_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?;

            Ok(UnresolvedRuleSelector::cli(value))
        }

        fn possible_values(&self) -> Option<Box<dyn Iterator<Item = PossibleValue> + '_>> {
            Some(Box::new(
                std::iter::once(PossibleValue::new("ALL").help("all rules")).chain(
                    Linter::iter()
                        .filter_map(|l| {
                            let prefix = l.common_prefix();
                            (!prefix.is_empty()).then(|| PossibleValue::new(prefix).help(l.name()))
                        })
                        .chain(RuleCodePrefix::iter().filter_map(|prefix| {
                            // Ex) `UP`
                            if prefix.short_code().is_empty() {
                                let code = prefix.linter().common_prefix();
                                let name = prefix.linter().name();
                                return Some(PossibleValue::new(code).help(name));

View on GitHub (pinned to d1087a4b9e)

Solutions

  1. Re-run with a UTF-8 locale (`export LANG=C.UTF-8`).
  2. Fix the calling script to emit UTF-8 rule codes.
  3. Verify each code is a real rule name (`ruff rule` lists them).
Defensive patterns

Strategy: validation

Validate before calling

#!/bin/sh
for sel in "$@"; do
  printf '%s' "$sel" | iconv -f UTF-8 -t UTF-8 >/dev/null 2>&1 || { echo "selector not UTF-8: $sel" >&2; exit 1; }
done
exec ruff check --select "$1" .

Prevention

When it happens

Trigger: `ruff check --select <non-UTF-8 bytes>` — a rule-code argument mangled by a legacy-locale shell or produced by a script emitting raw bytes.

Common situations: Locale mismatches in terminals or CI; scripts that build argv from byte-oriented sources; extremely rare interactively.

Understand the failure class

Related errors


AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20). Data as JSON: /api/errors/27220eea1d503071. Report an issue: GitHub.