{"record":{"id":"afab3bd49a157683","repo":"astral-sh/ruff","slug":"cannot-fix-self","errorCode":null,"errorMessage":"Cannot fix `{self}`","messagePattern":"Cannot fix `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/ruff_linter/src/rules/flake8_pytest_style/rules/unittest_assert.rs","lineNumber":464,"sourceCode":"                        node_index: ruff_python_ast::AtomicNodeIndex::NONE,\n                    },\n                    range_start: ruff_text_size::TextSize::default(),\n                    node_index: ruff_python_ast::AtomicNodeIndex::NONE,\n                };\n                let re_search = node2.into();\n                if matches!(self, UnittestAssert::Regex | UnittestAssert::RegexpMatches) {\n                    Ok(assert(&re_search, msg))\n                } else {\n                    let node = ast::ExprUnaryOp {\n                        op: UnaryOp::Not,\n                        operand: Box::new(re_search),\n                        range: TextRange::default(),\n                        node_index: ruff_python_ast::AtomicNodeIndex::NONE,\n                    };\n                    Ok(assert(&node.into(), msg))\n                }\n            }\n            _ => bail!(\"Cannot fix `{self}`\"),\n        }\n    }\n}\n","sourceCodeStart":446,"sourceCodeEnd":468,"githubUrl":"https://github.com/astral-sh/ruff/blob/15f3fe6b15a5f00172f34b0f542f8ea277f5a586/crates/ruff_linter/src/rules/flake8_pytest_style/rules/unittest_assert.rs#L446-L468","documentation":"This bail in `generate_assert` is the catch-all abort of the flake8-pytest-style unittest-assert-to-assert rewrite: the assertion method matched by PT009 has no corresponding libcst transformation, so no `assert` statement can be synthesized. The diagnostic is reported but the fix is marked unavailable.","triggerScenarios":"`ruff check --fix` on a unittest assertion call whose variant is not one of the supported rewrite shapes handled by the match arms above line 465 (e.g. less common assertion methods like `assertDictContainsSubset`-style or forms the rewriter doesn't model).","commonSituations":"Mixed unittest/pytest codebases hitting rarer assertion methods; calls built dynamically that pattern-match into the default branch of the rewrite.","solutions":["Rewrite the assertion manually as a plain `assert` with a comparison appropriate to the method","Suppress PT009 for the line with `# noqa: PT009` if the unittest style must stay","Disable PT009 (or its fix) in configuration for codebases that intentionally keep unittest assertions"],"exampleFix":"// before\nself.assertGreater(len(items), 0)\n// after\nassert len(items) > 0","handlingStrategy":"try-catch","validationCode":"// Prefer explicit rewrites for uncommon assertion methods:\n// treat self.assertX(...) calls not in the supported set (assertEqual, assertTrue, assertRaises, ...) as manual-migration cases.","typeGuard":"// In a pre-commit script: skip auto-fixing files containing unsupported methods:\ngrep -nE 'assert(Not)?(DictContainsSubset|CountEqual|NoLogs|Logs)' tests/ && echo 'manual migration needed'","tryCatchPattern":"// run fix selectively and continue on unfixable findings:\n$fix = ruff --fix --select PT009 .; if ($fix.unfixed > 0) { planManualMigration($fix.unfixedDiagnostics) }","preventionTips":["List target assertion methods before a unittest->pytest migration and hand-write mappings for the rare ones","Treat PT009 as diagnostic-only (unfixable) in config if the codebase uses exotic assertion methods","Do migrations in small batches so unfixable cases are reviewed"],"tags":["ruff","flake8-pytest-style","autofix","pytest"],"backgroundTag":"linter-autofix-skipped","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"}