{"record":{"id":"f2183252d655bd90","repo":"astral-sh/ruff","slug":"missing-argument-obj","errorCode":null,"errorMessage":"Missing argument `obj`","messagePattern":"Missing argument `obj`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff_linter/src/rules/flake8_pytest_style/rules/unittest_assert.rs","lineNumber":380,"sourceCode":"                    .get(\"expr\")\n                    .ok_or_else(|| anyhow!(\"Missing argument `expr`\"))?;\n                let msg = args.get(\"msg\").copied();\n                let cmp_op = if matches!(self, UnittestAssert::IsNone) {\n                    CmpOp::Is\n                } else {\n                    CmpOp::IsNot\n                };\n                let node = Expr::NoneLiteral(ast::ExprNoneLiteral {\n                    range: TextRange::default(),\n                    node_index: ruff_python_ast::AtomicNodeIndex::NONE,\n                });\n                let expr = compare(expr, cmp_op, &node);\n                Ok(assert(&expr, msg))\n            }\n            UnittestAssert::IsInstance | UnittestAssert::NotIsInstance => {\n                let obj = args\n                    .get(\"obj\")\n                    .ok_or_else(|| anyhow!(\"Missing argument `obj`\"))?;\n                let cls = args\n                    .get(\"cls\")\n                    .ok_or_else(|| anyhow!(\"Missing argument `cls`\"))?;\n                let msg = args.get(\"msg\").copied();\n                let node = ast::ExprName {\n                    id: Name::new_static(\"isinstance\"),\n                    ctx: ExprContext::Load,\n                    range: TextRange::default(),\n                    node_index: ruff_python_ast::AtomicNodeIndex::NONE,\n                };\n                let node1 = ast::ExprCall {\n                    func: Box::new(node.into()),\n                    arguments: Arguments {\n                        args: [(**obj).clone(), (**cls).clone()].into(),\n                        keywords: std::iter::empty().collect(),\n                        range: TextRange::default(),\n                        node_index: ruff_python_ast::AtomicNodeIndex::NONE,\n                    },","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/astral-sh/ruff/blob/15f3fe6b15a5f00172f34b0f542f8ea277f5a586/crates/ruff_linter/src/rules/flake8_pytest_style/rules/unittest_assert.rs#L362-L398","documentation":"For `assertIsInstance`/`assertNotIsInstance`, `generate_assert` emits `assert isinstance(obj, cls)`. The rewrite first requires the `obj` argument; when the mapped call arguments contain no `\"obj\"` entry, the transformation fails with this error.","triggerScenarios":"`UnittestAssert::IsInstance | NotIsInstance.generate_assert` where the call is missing the first positional arg and has no `obj=` keyword — e.g. `self.assertIsInstance()` or a call passing only `cls`/`msg`.","commonSituations":"Incomplete type-check assertions in test suites run through `ruff --fix`; helper classes defining `assertIsInstance` with a different signature mistaken for unittest methods.","solutions":["Complete the call: `self.assertIsInstance(value, SomeClass)`.","Ignore PT009 (per-file-ignores or global ignore) if the method is not unittest's.","If maintaining Ruff, verify the `arg_spec = ['obj', 'cls', 'msg']` mapping in `args_map`.","Check the reported source range to confirm the triggering call before changing configuration."],"exampleFix":"// before\nself.assertIsInstance(cls=MyClass)\n// after\nself.assertIsInstance(obj, MyClass)","handlingStrategy":"validation","validationCode":"def valid_isinstance_call(call_args, call_kwargs):\n    return len(call_args) >= 1 or 'obj' in call_kwargs","typeGuard":"def has_obj(args: tuple, kwargs: dict) -> bool:\n    return len(args) >= 1 or 'obj' in kwargs","tryCatchPattern":null,"preventionTips":["Pass the instance first: assertIsInstance(obj, cls).","Avoid custom methods named assertIsInstance with different signatures on test base classes.","Run lint in check-only mode in pre-commit; autofix only on clean files.","Keep type-check asserts complete even in skipped/xfail tests."],"tags":["linter","rust","pytest-style","argument-missing"],"backgroundTag":"missing-required-argument","analyzedSha":"15f3fe6b15a5f00172f34b0f542f8ea277f5a586","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}