astral-sh/ruff · error
Expected <FilePattern>:<RuleCode> pattern
Error message
Expected <FilePattern>:<RuleCode> pattern
What it means
Ruff parses CLI values for --per-file-ignores / --extend-per-file-ignores as PatternPrefixPair, which requires exactly one colon separating a file glob from a rule selector. The string given did not split into exactly two ':'-delimited tokens, so Ruff rejects it before reading any configuration. This is purely a command-line argument format error.
Source
Thrown at crates/ruff_linter/src/settings/types.rs:386
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PatternPrefixPair {
pub pattern: String,
pub prefix: UnresolvedRuleSelector,
}
impl PatternPrefixPair {
const EXPECTED_PATTERN: &'static str = "<FilePattern>:<RuleCode> pattern";
}
impl FromStr for PatternPrefixPair {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (pattern_str, code_string) = {
let tokens = s.split(':').collect::<Vec<_>>();
if tokens.len() != 2 {
bail!("Expected {}", Self::EXPECTED_PATTERN);
}
(tokens[0].trim(), tokens[1].trim())
};
let pattern = pattern_str.into();
let prefix = UnresolvedRuleSelector::cli(code_string);
Ok(Self { pattern, prefix })
}
}
#[derive(
Clone,
Copy,
Debug,
PartialOrd,
Ord,
PartialEq,
Eq,
Default,View on GitHub (pinned to d1087a4b9e)
Solutions
- Rewrite the value as '<FilePattern>:<RuleCode>', e.g. --per-file-ignores 'src/legacy/*.py:E501'
- Use a comma to pass multiple pairs: --per-file-ignores 'a.py:E501,b.py:F401'
- Prefer the pyproject.toml [tool.ruff.lint.per-file-ignores] table for anything non-trivial
Example fix
# before ruff check --per-file-ignores E501 . # after ruff check --per-file-ignores 'src/legacy/*.py:E501' .
Defensive patterns
Strategy: validation
Validate before calling
# bash: require exactly one colon before passing the flag pair='src/legacy/*.py:E501' if [[ "$(tr -cd ':' <<<"$pair" | wc -c)" -ne 1 ]]; then echo "need <FilePattern>:<RuleCode>, e.g. 'src/*.py:E501'" >&2; exit 1 fi ruff check --per-file-ignores "$pair" .
Prevention
- Remember the CLI form is one '<glob>:<RuleCode>' string per pair, comma-separated for multiple
- Keep complex per-file rules in the pyproject [tool.ruff.lint.per-file-ignores] table instead of CLI flags
- Escape Windows drive-path colons or use forward-slash relative globs
When it happens
Trigger: Passing a rule code without a file pattern (`--per-file-ignores E501`), passing only a pattern (`--per-file-ignores 'src/*'`), or using extra colons (`--per-file-ignores 'a.py:E5:01'`, or an unescaped Windows drive path like `C:\x.py:E501` which yields three tokens).
Common situations: Copy-pasting a pyproject.toml per-file-ignores value (which is a table, not a string) onto the CLI; assuming --per-file-ignores takes only a rule code; quoting mistakes in shell scripts.
Related errors
- Expected <Extension>:<LanguageCode> pattern
- No files found under the given path
- Unsupported serialization format for statistics: {:?}
- Working directory does not exist
- Expected {}
AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20).
Data as JSON: /api/errors/547c4b551fb0161f.
Report an issue: GitHub.