astral-sh/ruff · error

Missing argument `cls`

Error message

Missing argument `cls`

What it means

Same `isinstance` rewrite path, but for the `cls` argument: `assert isinstance(obj, cls)` needs both operands. When `args_map` lacks a `"cls"` entry, `generate_assert` returns this error and skips producing a fix.

Source

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

                let cmp_op = if matches!(self, UnittestAssert::IsNone) {
                    CmpOp::Is
                } else {
                    CmpOp::IsNot
                };
                let node = Expr::NoneLiteral(ast::ExprNoneLiteral {
                    range: TextRange::default(),
                    node_index: ruff_python_ast::AtomicNodeIndex::NONE,
                });
                let expr = compare(expr, cmp_op, &node);
                Ok(assert(&expr, msg))
            }
            UnittestAssert::IsInstance | UnittestAssert::NotIsInstance => {
                let obj = args
                    .get("obj")
                    .ok_or_else(|| anyhow!("Missing argument `obj`"))?;
                let cls = args
                    .get("cls")
                    .ok_or_else(|| anyhow!("Missing argument `cls`"))?;
                let msg = args.get("msg").copied();
                let node = ast::ExprName {
                    id: Name::new_static("isinstance"),
                    ctx: ExprContext::Load,
                    range: TextRange::default(),
                    node_index: ruff_python_ast::AtomicNodeIndex::NONE,
                };
                let node1 = ast::ExprCall {
                    func: Box::new(node.into()),
                    arguments: Arguments {
                        args: [(**obj).clone(), (**cls).clone()].into(),
                        keywords: std::iter::empty().collect(),
                        range: TextRange::default(),
                        node_index: ruff_python_ast::AtomicNodeIndex::NONE,
                    },
                    range_start: ruff_text_size::TextSize::default(),
                    node_index: ruff_python_ast::AtomicNodeIndex::NONE,
                };

View on GitHub (pinned to 15f3fe6b15)

Solutions

  1. Add the class argument: `self.assertIsInstance(value, ExpectedType)`.
  2. Suppress PT009 for that code if rewriting is not desired.
  3. While patching Ruff, check `args_map`'s positional zip — an extra/missing leading positional shifts names and drops `cls`.
  4. Re-run `ruff check --fix` to validate the rewrite completes.

Example fix

// before
self.assertIsInstance(response)
// after
self.assertIsInstance(response, dict)
Defensive patterns

Strategy: validation

Validate before calling

def valid_isinstance_call(call_args, call_kwargs):
    return (len(call_args) >= 2) or (len(call_args) == 1 and 'cls' in call_kwargs)

Type guard

def has_cls(args: tuple, kwargs: dict) -> bool:
    return len(args) >= 2 or 'cls' in kwargs

Prevention

When it happens

Trigger: `UnittestAssert::IsInstance | NotIsInstance.generate_assert` where the call supplied `obj` but no second positional arg and no `cls=` keyword, e.g. `self.assertIsInstance(value)`.

Common situations: Half-finished test assertions; class arguments removed during refactoring; non-unittest `assertIsInstance` helpers with different arity.

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/71853c5169b83deb. Report an issue: GitHub.