astral-sh/ruff · error

Expected {}

Error message

Expected {}

What it means

`PatternPrefixPair::from_str` parses CLI/config strings of the form `<FilePattern>:<RuleCode>` (used for per-file rule overrides). It throws `Expected <FilePattern>:<RuleCode> pattern` via anyhow when the string does not contain exactly one `:` producing exactly two tokens.

Source

Thrown at crates/ruff_linter/src/settings/types.rs:400

#[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 26f38c119c)

Solutions

  1. Write the value as `<glob>:<rule-code>`, e.g. `"tests/*:S101"`
  2. Ensure exactly one colon separates pattern and rule code; avoid extra colons
  3. Quote the value in TOML/CLI so shell expansion does not split it

Example fix

# before
[tool.ruff.lint.per-file-ignores]
"tests/*" = "S101"
# after
[tool.ruff.lint.per-file-ignores]
"tests/*" = "S101"  # correct form used by this pair type: "<FilePattern>:<RuleCode>"
Defensive patterns

Strategy: validation

Validate before calling

def validate_pattern_prefix_pair(value: str) -> bool:
    tokens = value.split(':')
    return len(tokens) == 2 and all(t.strip() for t in tokens)

assert validate_pattern_prefix_pair("tests/*:S101")

Prevention

When it happens

Trigger: Passing a value like `"foo.py"`, `"foo.py:E501:extra"`, or a value with no colon to settings that expect a pattern-prefix pair (e.g. `lint.per-file-ignores` style entries or `--per-file-target-version`-like options parsed into `PatternPrefixPair`).

Common situations: Typos in pyproject.toml/ruff.toml configuration; forgetting the `:E501` suffix on a glob; quoting issues that split the value; on Windows, drive letters (`C:...`) can distort the colon count.

Related errors


AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05). Data as JSON: /api/errors/a49906989199927b. Report an issue: GitHub.