astral-sh/ruff · error

Expected outer with to have indented body

Error message

Expected outer with to have indented body

What it means

Ruff's SIM117 autofix, after locating the outer `with` statement, expects its body to be a conventional indented block. If the outer `with` matches structurally but its body is not a `Suite::IndentedBlock` (e.g. it is represented as parenthesized/hugging statements or an unexpected suite form), the fixer cannot safely rewrite it and bails.

Source

Thrown at crates/ruff_linter/src/rules/flake8_simplify/rules/fix_with.rs:62

        let embedding = match_function_def(&mut tree)?;

        let indented_block = match_indented_block(&mut embedding.body)?;
        indented_block.indent = Some(outer_indent);

        let Some(statement) = indented_block.body.first_mut() else {
            bail!("Expected indented block to have at least one statement")
        };
        statement
    };

    let outer_with = match_with(statement)?;

    let With {
        body: Suite::IndentedBlock(outer_body),
        ..
    } = outer_with
    else {
        bail!("Expected outer with to have indented body")
    };

    let [Statement::Compound(CompoundStatement::With(inner_with))] = &mut *outer_body.body else {
        bail!("Expected one inner with statement");
    };

    outer_with.items.append(&mut inner_with.items);
    if outer_with.lpar.is_none() {
        outer_with.lpar.clone_from(&inner_with.lpar);
        outer_with.rpar.clone_from(&inner_with.rpar);
    }
    outer_with.body = inner_with.body.clone();

    // Reconstruct and reformat the code.
    let module_text = tree.codegen_stylist(stylist);
    let contents = if outer_indent.is_empty() {
        module_text
    } else {

View on GitHub (pinned to 26f38c119c)

Solutions

  1. Rewrite the nested `with` manually (combine contexts into one `with a as x, b as y:`)
  2. Ignore SIM117 for the offending file/line if the shape is intentional
  3. File a Ruff issue with the snippet since the fixer didn't expect this body form

Example fix

// before
with open('a') as a:
    with open('b') as b:
        use(a, b)
// after
with open('a') as a, open('b') as b:
    use(a, b)
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: `fix_multiple_with_statements` called `match_with` on the target statement and got a `With` node whose `body` field is not `Suite::IndentedBlock` — an unusual suite representation for the outer `with`.

Common situations: Nonstandard statement layouts (comments-only bodies, dedent edge cases, partial parses) when running `ruff --fix` over generated or heavily formatted code.

Related errors


AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05). Data as JSON: /api/errors/dfce8a44b91f06e8. Report an issue: GitHub.