{"record":{"id":"ed7cc7ebe58eb052","repo":"astral-sh/ruff","slug":"expected-simple-statement-to-be-an-assert","errorCode":null,"errorMessage":"Expected simple statement to be an assert","messagePattern":"Expected simple statement to be an assert","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff_linter/src/rules/flake8_pytest_style/rules/assertion.rs","lineNumber":773,"sourceCode":"        &mut tree.body\n    } else {\n        let [Statement::Compound(CompoundStatement::FunctionDef(embedding))] = &mut *tree.body\n        else {\n            bail!(\"Expected statement to be embedded in a function definition\")\n        };\n\n        let indented_block = match_indented_block(&mut embedding.body)?;\n        indented_block.indent = Some(outer_indent);\n\n        &mut indented_block.body\n    };\n\n    let [Statement::Simple(simple_statement_line)] = statements.as_slice() else {\n        bail!(\"Expected one simple statement\")\n    };\n\n    let [SmallStatement::Assert(assert_statement)] = simple_statement_line.body.as_slice() else {\n        bail!(\"Expected simple statement to be an assert\")\n    };\n\n    // Extract the individual conditions.\n    let mut conditions: Vec<Expression> = Vec::with_capacity(2);\n    match &assert_statement.test {\n        Expression::UnaryOperation(op) => {\n            if matches!(op.operator, libcst_native::UnaryOp::Not { .. }) {\n                if let Expression::BooleanOperation(boolean_operation) = &*op.expression {\n                    if matches!(boolean_operation.operator, BooleanOp::Or { .. }) {\n                        conditions.push(negate(&parenthesize(\n                            &boolean_operation.left,\n                            &op.expression,\n                        )));\n                        conditions.push(negate(&parenthesize(\n                            &boolean_operation.right,\n                            &op.expression,\n                        )));\n                    } else {","sourceCodeStart":755,"sourceCodeEnd":791,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff_linter/src/rules/flake8_pytest_style/rules/assertion.rs#L755-L791","documentation":"Internal consistency error in the flake8_pytest_style assertion rewriting helpers. After the enclosing statement list is located (either the module body or an embedded function body), the code destructures it expecting exactly one simple statement, and then expects that statement's small statements to begin with an assert. When the pattern match on Statement::Simple/SmallStatement::Assert fails, this bail fires: the AST shape produced by the caller (composite_condition) does not match the assumed structure of a single assert statement, so no pytest-style assertion transformation can be applied. It signals a bug in the caller's statement extraction rather than a condition the end user can trigger.","triggerScenarios":"Thrown at crates/ruff_linter/src/rules/flake8_pytest_style/rules/assertion.rs:773 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check the statement kind before entering the rewrite path","Skip the autofix when the small statement is not an assert"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}