astral-sh/ruff · warning

indented block to start with indentation

Error message

indented block to start with indentation

What it means

Also part of the PLR5501 `elif` rewrite fix. After dedenting the inner `if` block, the fixer expects the dedented text to begin with the outer clause's indentation so it can prepend `el` to form `elif`. If the reconstructed string does not start with the computed indentation prefix (inconsistent indentation between the `else` and the inner `if`), the rewrite is abandoned.

Source

Thrown at crates/ruff_linter/src/rules/pylint/rules/collapsible_else_if.rs:145

        indexer,
        stylist,
    )?;

    // If there's trivia, restore it
    let trivia = if trivia_range.is_empty() {
        None
    } else {
        let indented_trivia =
            adjust_indentation(trivia_range, indentation, locator, indexer, stylist)?;
        Some(Edit::insertion(
            indented_trivia,
            locator.line_start(else_clause.start()),
        ))
    };

    // Strip the indent from the first line of the `if` statement, and add `el` to the start.
    let Some(unindented) = indented.strip_prefix(indentation) else {
        return Err(anyhow::anyhow!("indented block to start with indentation"));
    };
    let indented = format!("{indentation}el{unindented}");

    Ok(Fix::safe_edits(
        Edit::replacement(
            indented,
            locator.line_start(else_clause.start()),
            inner_if_line_end,
        ),
        trivia,
    ))
}

View on GitHub (pinned to 26f38c119c)

Solutions

  1. Re-indent the `else` block and the nested `if` with the same whitespace, then rerun the fix
  2. Manually convert `else: if ...` to `elif ...`
  3. Run a formatter (e.g. `ruff format`) to normalize indentation before autofixing

Example fix

# before (mixed indentation; fix fails)
else:
    if b:      # indented differently from else
        g()
# after (uniform indentation)
else:
  if b:
    g()
# becomes elif b:\n    g()
Defensive patterns

Strategy: validation

Validate before calling

def consistent_indent(line_else: str, line_if: str) -> bool:
    ie = len(line_else) - len(line_else.lstrip())
    ii = len(line_if) - len(line_if.lstrip())
    return ii > ie  # inner if strictly deeper than else, same style

Prevention

When it happens

Trigger: `convert_to_elif` computed an `indentation` string, adjusted the inner block's indentation via `adjust_indentation`, but the result fails `strip_prefix(indentation)` — i.e. the inner `if`'s line does not share the `else` clause's indentation style (e.g. `else` indented with tabs but the inner `if` with spaces).

Common situations: Files mixing tabs and spaces across the `else`/nested-`if` lines; code edited by tools with different indent settings; users of `ruff --fix` see the nested-if diagnostic remain unfixed.

Related errors


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