astral-sh/ruff · error

Missing argument `expr`

Error message

Missing argument `expr`

What it means

The flake8-pytest-style `unittest_assert` generator reconstructs calls like `self.assertTrue(expr)` from recorded arguments. Variants `assertTrue`/`assertFalse`/`failUnless`/`failIf` require an `expr` argument; if the args map lacks it, generation cannot build a valid call and fails with this internal error.

Source

Thrown at crates/ruff_linter/src/rules/flake8_pytest_style/rules/unittest_assert.rs:289

                }
            }) {
                args_map.insert(arg_name, value);
            }
        }

        Ok(args_map)
    }

    pub(crate) fn generate_assert(self, args: &[Expr], keywords: &[Keyword]) -> Result<Stmt> {
        let args = self.args_map(args, keywords)?;
        match self {
            UnittestAssert::True
            | UnittestAssert::False
            | UnittestAssert::FailUnless
            | UnittestAssert::FailIf => {
                let expr = *args
                    .get("expr")
                    .ok_or_else(|| anyhow!("Missing argument `expr`"))?;
                let msg = args.get("msg").copied();
                Ok(
                    if matches!(self, UnittestAssert::False | UnittestAssert::FailIf) {
                        assert(
                            &Expr::UnaryOp(ast::ExprUnaryOp {
                                op: UnaryOp::Not,
                                operand: Box::new(expr.clone()),
                                range: TextRange::default(),
                                node_index: ruff_python_ast::AtomicNodeIndex::NONE,
                            }),
                            msg,
                        )
                    } else {
                        assert(expr, msg)
                    },
                )
            }
            UnittestAssert::Equal

View on GitHub (pinned to 15f3fe6b15)

Solutions

  1. Ensure the caller inserts the expression under the `expr` key before calling `generate_assert`.
  2. Check the variant: `assertTrue`-family asserts always need an expression; use `Fail`/argument-less variants for message-only assertions.
  3. If you hit this from Ruff itself, capture the file and report it as a fixer bug upstream.

Example fix

// before
let mut args = FxHashMap::default();
args.insert("msg", msg); // expr missing
unittest_assert.generate_assert(&args)?

// after
let mut args = FxHashMap::default();
args.insert("expr", expr);
args.insert("msg", msg);
unittest_assert.generate_assert(&args)?
Defensive patterns

Strategy: validation

Validate before calling

// validate args before generate_assert
if (!args.has('expr') && ['True','False','FailUnless','FailIf'].includes(variant)) {
  throw new Error(`${variant} requires an expr argument`);
}

Type guard

fn has_expr(args: &FxHashMap<&str, &str>) -> bool { args.contains_key("expr") }

Try / catch

match assert.generate_assert(&args) {
    Err(e) if e.to_string() == "Missing argument `expr`" => {
        eprintln!("Bug: {} assertions need an expr; check the caller that builds args", variant);
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `UnittestAssert::generate_assert` with an `args` map missing the `"expr"` key for one of the `True`, `False`, `FailUnless`, or `FailIf` variants.

Common situations: Fixer/refactor code paths (e.g. translating between pytest and unittest assertion styles) constructing the args map incorrectly, or upstream callers passing assertion data captured without the expression.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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