astral-sh/ruff · warning

Expected a call or lambda

Error message

Expected a call or lambda

What it means

Also part of the C417/unnecessary-map fix. The fixer accepts either a single argument that is a call, or two arguments where the first is a lambda. If the outer `map(...)` call's argument list matches neither shape (zero, one non-call, or three-plus arguments), it bails with this message.

Source

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

    let mut tree = match_expression(module_text)?;
    let call = match_call_mut(&mut tree)?;

    let (lambda, iter) = match call.args.as_slice() {
        [call] => {
            let call = match_call(&call.value)?;
            let [lambda, iter] = call.args.as_slice() else {
                bail!("Expected two arguments");
            };
            let lambda = match_lambda(&lambda.value)?;
            let iter = &iter.value;
            (lambda, iter)
        }
        [lambda, iter] => {
            let lambda = match_lambda(&lambda.value)?;
            let iter = &iter.value;
            (lambda, iter)
        }
        _ => bail!("Expected a call or lambda"),
    };

    // Format the lambda target.
    let target = match lambda.params.params.as_slice() {
        // Ex) `lambda: x`
        [] => AssignTargetExpression::Name(Box::new(Name {
            value: "_",
            lpar: vec![],
            rpar: vec![],
        })),
        // Ex) `lambda x: y`
        [param] => AssignTargetExpression::Name(Box::new(param.name.clone())),
        // Ex) `lambda x, y: z`
        params => AssignTargetExpression::Tuple(Box::new(Tuple {
            elements: params
                .iter()
                .map(|param| Element::Simple {
                    value: Expression::Name(Box::new(param.name.clone())),

View on GitHub (pinned to 26f38c119c)

Solutions

  1. Re-run `ruff check --fix` so the diagnostic matches the current argument list.
  2. Convert multi-iterable `map(f, xs, ys)` to a `zip`-based comprehension manually: `(f(x, y) for x, y in zip(xs, ys))`.
  3. Suppress C417 with noqa for intentionally complex `map` usage.

Example fix

// before
result = map(combine, keys, values)
// after
result = (combine(k, v) for k, v in zip(keys, values))
Defensive patterns

Strategy: type-guard

Validate before calling

shape_ok = (len(m.args) == 1 and isinstance(m.args[0], ast.Call)) or (len(m.args) == 2 and isinstance(m.args[0], ast.Lambda))

Type guard

def fixable_map_shape(m):
    return (isinstance(m, ast.Call) and
            ((len(m.args) == 1 and isinstance(m.args[0], ast.Call)) or
             (len(m.args) == 2 and isinstance(m.args[0], ast.Lambda))))

Try / catch

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

Prevention

When it happens

Trigger: `ruff check --fix` on `map(f, a, b)` (multiple iterables), `map(x)` where `x` is not a call, or `map()` with no arguments.

Common situations: Multi-iterable `map` calls that a stale C417 diagnostic still points at; `itertools`-style refactorings leaving `map` with extra arguments; hand-written code fed into the fixer.

Related errors


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