astral-sh/ruff · warning

Expected colon after test

Error message

Expected colon after test

What it means

This error is raised while building the fix for SIM114 (combine `if` branches with identical arms) when the fixer cannot locate the colon after the `if` test of a branch. Without the colon's position, the fixer cannot compute the text range to splice when merging two identical branches, so it aborts the fix.

Source

Thrown at crates/ruff_linter/src/rules/flake8_simplify/rules/if_with_same_arms.rs:122

            )
        });
    }
}

/// Generate a [`Fix`] to merge two [`IfElifBranch`] branches.
fn merge_branches(
    stmt_if: &ast::StmtIf,
    current_branch: &IfElifBranch,
    following_branch: &IfElifBranch,
    locator: &Locator,
    tokens: &ruff_python_ast::token::Tokens,
) -> Result<Fix> {
    // Identify the colon (`:`) at the end of the current branch's test.
    let Some(current_branch_colon) =
        SimpleTokenizer::starts_at(current_branch.test.end(), locator.contents())
            .find(|token| token.kind == SimpleTokenKind::Colon)
    else {
        return Err(anyhow::anyhow!("Expected colon after test"));
    };

    let deletion_edit = Edit::deletion(
        locator.full_line_end(current_branch.end()),
        locator.full_line_end(following_branch.end()),
    );

    // If the following test isn't parenthesized, consider parenthesizing it.
    let following_branch_test = if let Some(range) =
        parenthesized_range(following_branch.test.into(), stmt_if.into(), tokens)
    {
        Cow::Borrowed(locator.slice(range))
    } else if matches!(
        following_branch.test,
        Expr::Lambda(_) | Expr::Named(_) | Expr::If(_)
    ) {
        // If the following expressions binds more tightly than `or`, parenthesize it.
        Cow::Owned(format!("({})", locator.slice(following_branch.test)))

View on GitHub (pinned to 26f38c119c)

Solutions

  1. Reformat the `if`/`elif` statements so the test expression ends with a normal `:` and rerun the fix
  2. Manually merge the identical branches by replacing `elif` with `or` or deleting the duplicate branch
  3. Report a reproducing snippet upstream so the fixer can be made robust

Example fix

# before (two identical branches)
if x == 1:
    do()
elif x == 2:
    do()
# after (combined)
if x in (1, 2):
    do()
Defensive patterns

Strategy: try-catch

Try / catch

let fix = merge_branches(...).unwrap_or_else(|_| {
    // emit diagnostic without fix; log "Expected colon after test"
    Fix::empty()
});

Prevention

When it happens

Trigger: `merge_branches` scans the locator's contents from the branch's test expression to find a colon token; if the token at the expected end position of the test is not a Colon (unexpected token layout in the parsed source), the fix returns Err('Expected colon after test').

Common situations: Autofixing `if/elif` chains with identical bodies where the source has irregular token layout; seen by users of `ruff --fix` as an unfixed diagnostic or by plugin/test developers consuming the fix API.

Related errors


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