astral-sh/ruff · warning

Expected container to use a key as the first element

Error message

Expected container to use a key as the first element

What it means

Third check in the same C417 dict-comprehension fix: the first element of the lambda body's pair container must be a simple (starless, unpackless) expression to serve as the key. Starred elements, slices with unusual nodes, etc. cannot become dict keys in the generated comprehension, so the fixer bails.

Source

Thrown at crates/ruff_linter/src/rules/flake8_comprehensions/fixes.rs:785

                lpar: vec![],
                rpar: vec![],
                lbrace: LeftCurlyBrace::default(),
                rbrace: RightCurlyBrace::default(),
            }));
        }
        ObjectType::Dict => {
            let elements = match lambda.body.as_ref() {
                Expression::Tuple(tuple) => &tuple.elements,
                Expression::List(list) => &list.elements,
                _ => {
                    bail!("Expected tuple or list for dictionary comprehension")
                }
            };
            let [key, value] = elements.as_slice() else {
                bail!("Expected container to include two elements");
            };
            let Element::Simple { value: key, .. } = key else {
                bail!("Expected container to use a key as the first element");
            };
            let Element::Simple { value, .. } = value else {
                bail!("Expected container to use a value as the second element");
            };

            tree = Expression::DictComp(Box::new(DictComp {
                for_in: compfor,
                lpar: vec![],
                rpar: vec![],
                key: Box::new(key.clone()),
                value: Box::new(value.clone()),
                lbrace: LeftCurlyBrace::default(),
                rbrace: RightCurlyBrace::default(),
                whitespace_before_colon: ParenthesizableWhitespace::default(),
                whitespace_after_colon: ParenthesizableWhitespace::SimpleWhitespace(
                    SimpleWhitespace(" "),
                ),
            }));

View on GitHub (pinned to 26f38c119c)

Solutions

  1. Replace the starred element with an explicit expression (e.g. `x[0]`) so the fix can apply.
  2. Rewrite as a manual dict comprehension: `{k: v for ...}` including whatever unpacking you need.
  3. Add `# noqa: C417` if starred/unpacked keys are intentional.

Example fix

// before
d = dict(map(lambda x: (*x[:2],), rows))
// after
d = {x[0]: x[1] for x in rows}
Defensive patterns

Strategy: type-guard

Validate before calling

ok = not isinstance(lam.body.elts[0], ast.Starred)

Type guard

def simple_key(body):
    return (isinstance(body, (ast.Tuple, ast.List)) and len(body.elts) == 2
            and not isinstance(body.elts[0], ast.Starred)
            and not isinstance(body.elts[1], ast.Starred))

Try / catch

try:
    apply_autofix(diagnostic)
except Exception:
    rewrite_with_explicit_indexing()

Prevention

When it happens

Trigger: `ruff check --fix` on `dict(map(lambda x: (*x, y), items))` or bodies whose first element is a starred expression like `lambda k: (*a, b)`.

Common situations: Unpacking-heavy lambda bodies from data-processing code; refactors introducing starred args into tuple bodies; stale diagnostics after edits.

Related errors


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