astral-sh/ruff · error

Missing argument `first`

Error message

Missing argument `first`

What it means

Ruff's flake8-pytest-style rewrite of unittest asserts (PT009, `generate_assert`) converts `self.assertLess`/`assertLessEqual`/`assertIs`/`assertIsNot` calls into plain `assert first <op> second` expressions. It first builds a map from argument names to expressions (`args_map`), then looks up `first`. If the call provides no first argument (positionally or by keyword), the rewrite cannot build the replacement and aborts with this error.

Source

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

                        assert(expr, msg)
                    },
                )
            }
            UnittestAssert::Equal
            | UnittestAssert::Equals
            | UnittestAssert::FailUnlessEqual
            | UnittestAssert::NotEqual
            | UnittestAssert::NotEquals
            | UnittestAssert::FailIfEqual
            | UnittestAssert::Greater
            | UnittestAssert::GreaterEqual
            | UnittestAssert::Less
            | UnittestAssert::LessEqual
            | UnittestAssert::Is
            | UnittestAssert::IsNot => {
                let first = args
                    .get("first")
                    .ok_or_else(|| anyhow!("Missing argument `first`"))?;
                let second = args
                    .get("second")
                    .ok_or_else(|| anyhow!("Missing argument `second`"))?;
                let msg = args.get("msg").copied();
                let cmp_op = match self {
                    UnittestAssert::Equal
                    | UnittestAssert::Equals
                    | UnittestAssert::FailUnlessEqual => CmpOp::Eq,
                    UnittestAssert::NotEqual
                    | UnittestAssert::NotEquals
                    | UnittestAssert::FailIfEqual => CmpOp::NotEq,
                    UnittestAssert::Greater => CmpOp::Gt,
                    UnittestAssert::GreaterEqual => CmpOp::GtE,
                    UnittestAssert::Less => CmpOp::Lt,
                    UnittestAssert::LessEqual => CmpOp::LtE,
                    UnittestAssert::Is => CmpOp::Is,
                    UnittestAssert::IsNot => CmpOp::IsNot,
                    _ => unreachable!(),

View on GitHub (pinned to 15f3fe6b15)

Solutions

  1. Fix the flagged call so it passes two arguments: `self.assertLess(a, b)`.
  2. Confirm the matched method is genuinely a unittest assert; suppress PT009 for files with custom same-named helpers.
  3. If editing Ruff itself, check that `args_map` zipped `arg_spec` names with positional args correctly.
  4. Re-run `ruff check --fix` after correcting the test call.

Example fix

// before
def test(self):
    self.assertLess()
// after
def test(self):
    self.assertLess(actual, expected)
Defensive patterns

Strategy: validation

Validate before calling

import inspect

def has_two_operands(obj, name):
    method = getattr(obj, name, None)
    if not callable(method):
        return False
    required = [p for p in inspect.signature(method).parameters.values() if p.default is inspect.Parameter.empty]
    return len(required) >= 2

assert has_two_operands(self, 'assertLess'), 'assertLess needs (first, second)'

Type guard

def has_first_operand(args: tuple, kwargs: dict) -> bool:
    return len(args) >= 1 or 'first' in kwargs

Prevention

When it happens

Trigger: `UnittestAssert::Less/LessEqual/Is/IsNot.generate_assert(args, keywords)` where the mapped args contain no `"first"` entry — e.g. a source call `self.assertLess()` with zero args, or fewer positional args than the arg_spec (`first`, `second`, `msg`).

Common situations: Running `ruff --fix` on test code calling `assertLess`/`assertIs` etc. with an incomplete argument list; dynamically bound methods matching the assert name but not unittest's signature; in-progress edits to test files.

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/6dbdfe24c5d1b812. Report an issue: GitHub.